Browse Source

Merge branch 'master' into shaderpipeline

rdb 6 years ago
parent
commit
afd7525963
100 changed files with 1189 additions and 5069 deletions
  1. 4 1
      .gitignore
  2. 35 0
      BACKERS.md
  3. 29 5
      README.md
  4. 11 0
      contrib/src/ai/aiBehaviors.cxx
  5. 0 1
      contrib/src/ai/aiGlobals.h
  6. 3 0
      contrib/src/ai/arrival.cxx
  7. 2 0
      contrib/src/ai/obstacleAvoidance.cxx
  8. 2 0
      contrib/src/ai/pathFind.cxx
  9. 14 0
      contrib/src/ai/pathFollow.cxx
  10. 1 1
      contrib/src/rplight/shadowAtlas.h
  11. 0 84
      direct/src/controls/GravityWalker.py
  12. 0 45
      direct/src/controls/PhysicsWalker.py
  13. 13 1
      direct/src/dist/commands.py
  14. 14 5
      direct/src/filter/FilterManager.py
  15. 18 3
      direct/src/gui/DirectOptionMenu.py
  16. 6 4
      direct/src/gui/DirectScrolledFrame.py
  17. 1 19
      direct/src/interval/SoundInterval.py
  18. 18 0
      direct/src/showbase/BufferViewer.py
  19. 3 2
      direct/src/showbase/Messenger.py
  20. 8 5
      direct/src/showbase/PythonUtil.py
  21. 2 3
      direct/src/showbase/SfxPlayer.py
  22. 18 6
      direct/src/showbase/ShowBase.py
  23. 9 7
      direct/src/showutil/TexMemWatcher.py
  24. 0 23
      direct/src/stdpy/threading.py
  25. 4 7
      direct/src/task/Task.py
  26. 8 4
      direct/src/tkpanels/AnimPanel.py
  27. 40 31
      direct/src/tkpanels/ParticlePanel.py
  28. 32 17
      direct/src/tkwidgets/Valuator.py
  29. 0 108
      dmodels/src/level_editor/donaldsDockColors.txt
  30. 0 64
      dmodels/src/level_editor/donaldsDockStyles.txt
  31. BIN
      dmodels/src/level_editor/donalds_dock_layout.flt
  32. 0 61
      dmodels/src/level_editor/minniesMelodyLandColors.txt
  33. 0 79
      dmodels/src/level_editor/minniesMelodyLandStyles.txt
  34. BIN
      dmodels/src/level_editor/minnies_melody_land_layout.flt
  35. 0 65
      dmodels/src/level_editor/theBurrrghColors.txt
  36. 0 90
      dmodels/src/level_editor/theBurrrghStyles.txt
  37. BIN
      dmodels/src/level_editor/the_burrrgh_layout.flt
  38. 0 106
      dmodels/src/level_editor/toontownCentralColors.txt
  39. 0 84
      dmodels/src/level_editor/toontownCentralStyles.txt
  40. BIN
      dmodels/src/level_editor/toontown_central_layout.flt
  41. 62 0
      doc/ReleaseNotes
  42. 0 47
      dtool/src/dtoolbase/dllbase.txt
  43. 1 1
      dtool/src/dtoolbase/mutexWin32Impl.I
  44. 96 43
      dtool/src/dtoolutil/executionEnvironment.cxx
  45. 317 0
      dtool/src/dtoolutil/iostream_ext.cxx
  46. 53 0
      dtool/src/dtoolutil/iostream_ext.h
  47. 1 0
      dtool/src/dtoolutil/p3dtoolutil_ext_composite.cxx
  48. 16 3
      dtool/src/interrogate/functionRemap.cxx
  49. 20 8
      dtool/src/interrogate/interfaceMakerPythonNative.cxx
  50. 1 1
      dtool/src/interrogate/interfaceMakerPythonNative.h
  51. 6 3
      dtool/src/interrogate/interrogate.cxx
  52. 13 0
      dtool/src/interrogatedb/py_panda.I
  53. 2 0
      dtool/src/interrogatedb/py_panda.h
  54. 1 0
      dtool/src/interrogatedb/py_wrappers.cxx
  55. 26 13
      dtool/src/parser-inc/iostream
  56. 24 0
      dtool/src/prc/encryptStream.cxx
  57. 3 0
      dtool/src/prc/encryptStream.h
  58. 18 0
      dtool/src/prc/encryptStreamBuf.I
  59. 54 3
      dtool/src/prc/encryptStreamBuf.cxx
  60. 9 0
      dtool/src/prc/encryptStreamBuf.h
  61. 25 1
      dtool/src/prc/streamReader.I
  62. 2 0
      dtool/src/prc/streamReader.h
  63. 28 1
      dtool/src/prc/streamWriter.I
  64. 2 0
      dtool/src/prc/streamWriter.h
  65. 2 2
      makepanda/makepackage.py
  66. 52 17
      makepanda/makepanda.py
  67. 0 9
      makepanda/makepanda.vcproj
  68. 9 2
      makepanda/makepandacore.py
  69. 15 2
      makepanda/makewheel.py
  70. 16 13
      makepanda/test_wheel.py
  71. 3 3
      panda/src/audio/audio.h
  72. 0 8
      panda/src/audio/audioManager.cxx
  73. 3 6
      panda/src/audio/audioManager.h
  74. 0 17
      panda/src/audio/audioSound.cxx
  75. 4 11
      panda/src/audio/audioSound.h
  76. 0 23
      panda/src/audio/config_audio.cxx
  77. 1 13
      panda/src/audio/config_audio.h
  78. 4 4
      panda/src/audio/nullAudioManager.h
  79. 4 4
      panda/src/audio/nullAudioSound.h
  80. 0 102
      panda/src/audiotraits/config_milesAudio.cxx
  81. 0 37
      panda/src/audiotraits/config_milesAudio.h
  82. 0 39
      panda/src/audiotraits/globalMilesManager.I
  83. 0 446
      panda/src/audiotraits/globalMilesManager.cxx
  84. 0 117
      panda/src/audiotraits/globalMilesManager.h
  85. 0 1121
      panda/src/audiotraits/milesAudioManager.cxx
  86. 0 198
      panda/src/audiotraits/milesAudioManager.h
  87. 0 13
      panda/src/audiotraits/milesAudioSample.I
  88. 0 530
      panda/src/audiotraits/milesAudioSample.cxx
  89. 0 103
      panda/src/audiotraits/milesAudioSample.h
  90. 0 12
      panda/src/audiotraits/milesAudioSequence.I
  91. 0 331
      panda/src/audiotraits/milesAudioSequence.cxx
  92. 0 88
      panda/src/audiotraits/milesAudioSequence.h
  93. 0 12
      panda/src/audiotraits/milesAudioSound.I
  94. 0 205
      panda/src/audiotraits/milesAudioSound.cxx
  95. 0 107
      panda/src/audiotraits/milesAudioSound.h
  96. 0 12
      panda/src/audiotraits/milesAudioStream.I
  97. 0 310
      panda/src/audiotraits/milesAudioStream.cxx
  98. 0 87
      panda/src/audiotraits/milesAudioStream.h
  99. 0 9
      panda/src/audiotraits/miles_audio_composite1.cxx
  100. 1 1
      panda/src/audiotraits/openalAudioManager.cxx

+ 4 - 1
.gitignore

@@ -4,11 +4,12 @@
 /targetroot/
 /dstroot/
 
-# Core dumps
+# Core dumps and traces
 core
 core.*
 vgcore.*
 *.core
+*.trace
 
 # Editor files/directories
 *.save
@@ -26,6 +27,7 @@ vgcore.*
 /+DESC
 /+MANIFEST
 /pkg-plist
+/debug.ks
 
 # Produced installer/executables
 /*.exe
@@ -36,6 +38,7 @@ vgcore.*
 /*.dmg
 /*.whl
 /*.txz
+/*.apk
 
 # CMake
 /build/

+ 35 - 0
BACKERS.md

@@ -0,0 +1,35 @@
+# Panda3D Backers
+
+This is a list of all the people who are contributing financially to Panda3D.  If you'd like to join them, visit [our campaign on OpenCollective](https://opencollective.com/panda3d)!
+
+## Gold Sponsors
+
+![Gold Sponsors](https://opencollective.com/panda3d/tiers/gold-sponsor.svg?avatarHeight=48&width=600)
+
+* [tcdude](https://opencollective.com/tizilogic)
+
+## Bronze Sponsors
+
+![Bronze Sponsors](https://opencollective.com/panda3d/tiers/bronze-sponsor.svg?avatarHeight=48&width=600)
+
+* [Mitchell Stokes](https://opencollective.com/mitchell-stokes)
+* [Daniel Stokes](https://opencollective.com/daniel-stokes)
+* [David Rose](https://opencollective.com/david-rose)
+* [Carnetsoft](https://cs-driving-simulator.com/)
+
+## Benefactors
+
+![Benefactors](https://opencollective.com/panda3d/tiers/benefactor.svg?avatarHeight=48&width=600)
+
+* Sam Edwards
+* Max Voss
+
+## Enthusiasts
+
+![Benefactors](https://opencollective.com/panda3d/tiers/enthusiast.svg?avatarHeight=48&width=600)
+
+* Eric Thomson
+
+## Backers
+
+![Backers](https://opencollective.com/panda3d/tiers/backer.svg?avatarHeight=48&width=600)

+ 29 - 5
README.md

@@ -1,4 +1,6 @@
 [![Build Status](https://travis-ci.org/panda3d/panda3d.svg?branch=master)](https://travis-ci.org/panda3d/panda3d)
+[![OpenCollective](https://opencollective.com/panda3d/backers/badge.svg)](https://opencollective.com/panda3d)
+[![OpenCollective](https://opencollective.com/panda3d/sponsors/badge.svg)](https://opencollective.com/panda3d)
 
 <img src="https://avatars2.githubusercontent.com/u/590956?v=3&s=500" align="right" width="200"/>
 
@@ -22,7 +24,7 @@ Installing Panda3D
 ==================
 
 The latest Panda3D SDK can be downloaded from
-[this page](https://www.panda3d.org/download/sdk-1-10-0/).
+[this page](https://www.panda3d.org/download/sdk-1-10-3/).
 If you are familiar with installing Python packages, you can use
 the following comand:
 
@@ -62,8 +64,8 @@ depending on whether you are on a 32-bit or 64-bit system, or you can
 [click here](https://github.com/rdb/panda3d-thirdparty) for instructions on
 building them from source.
 
-https://www.panda3d.org/download/panda3d-1.10.1/panda3d-1.10.1-tools-win64.zip
-https://www.panda3d.org/download/panda3d-1.10.1/panda3d-1.10.1-tools-win32.zip
+https://www.panda3d.org/download/panda3d-1.10.3/panda3d-1.10.3-tools-win64.zip
+https://www.panda3d.org/download/panda3d-1.10.3/panda3d-1.10.3-tools-win32.zip
 
 After acquiring these dependencies, you may simply build Panda3D from the
 command prompt using the following command.  (Change `14.1` to `14` if you are
@@ -133,7 +135,7 @@ macOS
 -----
 
 On macOS, you will need to download a set of precompiled thirdparty packages in order to
-compile Panda3D, which can be acquired from [here](https://www.panda3d.org/download/panda3d-1.10.1/panda3d-1.10.1-tools-mac.tar.gz).
+compile Panda3D, which can be acquired from [here](https://www.panda3d.org/download/panda3d-1.10.3/panda3d-1.10.3-tools-mac.tar.gz).
 
 After placing the thirdparty directory inside the panda3d source directory,
 you may build Panda3D using a command like the following:
@@ -189,7 +191,7 @@ pkg install python-dev termux-tools ndk-stl ndk-sysroot clang libvorbis-dev libo
 Then, you can build and install the .apk right away using these commands:
 
 ```bash
-python makepanda/makepanda.py --everything --target android-21 --installer
+python makepanda/makepanda.py --everything --target android-21 --no-tiff --installer
 xdg-open panda3d.apk
 ```
 
@@ -228,3 +230,25 @@ models that are necessary for the developers to reproduce the issue.
 
 If you're not sure whether you've encountered a bug, feel free to ask about
 it in the forums or the IRC channel first.
+
+Supporting the Project
+======================
+
+If you would like to support the project financially, visit
+[our campaign on OpenCollective](https://opencollective.com/panda3d).  Your
+contributions help us accelerate the development of Panda3D.
+
+For the list of backers, see the [BACKERS.md](BACKERS.md) file or visit the
+[Sponsors page](https://www.panda3d.org/sponsors) on our web site.  Thank you
+to everyone who has donated!
+
+<a href="https://opencollective.com/panda3d" target="_blank">
+  <img src="https://opencollective.com/panda3d/contribute/[email protected]?color=blue" width=300 />
+</a>
+
+### Gold Sponsors
+[![](https://opencollective.com/panda3d/tiers/gold-sponsor/0/avatar.svg?avatarHeight=128)](https://opencollective.com/panda3d/tiers/gold-sponsor/0/website)
+[![](https://opencollective.com/panda3d/tiers/gold-sponsor/1/avatar.svg?avatarHeight=128)](https://opencollective.com/panda3d/tiers/gold-sponsor/1/website)
+[![](https://opencollective.com/panda3d/tiers/gold-sponsor/2/avatar.svg?avatarHeight=128)](https://opencollective.com/panda3d/tiers/gold-sponsor/2/website)
+[![](https://opencollective.com/panda3d/tiers/gold-sponsor/3/avatar.svg?avatarHeight=128)](https://opencollective.com/panda3d/tiers/gold-sponsor/3/website)
+[![](https://opencollective.com/panda3d/tiers/gold-sponsor/4/avatar.svg?avatarHeight=128)](https://opencollective.com/panda3d/tiers/gold-sponsor/4/website)

+ 11 - 0
contrib/src/ai/aiBehaviors.cxx

@@ -13,6 +13,17 @@
 
 #include "aiBehaviors.h"
 
+#include "arrival.h"
+#include "evade.h"
+#include "flee.h"
+#include "flock.h"
+#include "obstacleAvoidance.h"
+#include "pathFind.h"
+#include "pathFollow.h"
+#include "pursue.h"
+#include "seek.h"
+#include "wander.h"
+
 using std::cout;
 using std::endl;
 using std::string;

+ 0 - 1
contrib/src/ai/aiGlobals.h

@@ -15,7 +15,6 @@
 #define _AI_GLOBALS_H
 
 #include "config_ai.h"
-#include "pandaFramework.h"
 #include "textNode.h"
 #include "pandaSystem.h"
 

+ 3 - 0
contrib/src/ai/arrival.cxx

@@ -13,6 +13,9 @@
 
 #include "arrival.h"
 
+#include "pursue.h"
+#include "seek.h"
+
 Arrival::Arrival(AICharacter *ai_ch, double distance) {
   _ai_char = ai_ch;
 

+ 2 - 0
contrib/src/ai/obstacleAvoidance.cxx

@@ -13,6 +13,8 @@
 
 #include "obstacleAvoidance.h"
 
+#include "aiWorld.h"
+
 ObstacleAvoidance::
 ObstacleAvoidance(AICharacter *ai_char, float feeler_length) {
   _ai_char = ai_char;

+ 2 - 0
contrib/src/ai/pathFind.cxx

@@ -13,6 +13,8 @@
 
 #include "pathFind.h"
 
+#include "pathFollow.h"
+
 using std::cout;
 using std::endl;
 using std::string;

+ 14 - 0
contrib/src/ai/pathFollow.cxx

@@ -1,6 +1,20 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file pathFind.cxx
+ * @author Deepak, John, Navin
+ * @date 2009-10-24
+ */
 
 #include "pathFollow.h"
 
+#include "pathFind.h"
+
 PathFollow::PathFollow(AICharacter *ai_ch, float follow_wt) {
     _follow_weight = follow_wt;
   _curr_path_waypoint = -1;

+ 1 - 1
contrib/src/rplight/shadowAtlas.h

@@ -28,7 +28,7 @@
 #define SHADOWATLAS_H
 
 #include "pandabase.h"
-#include "lvecBase4.h"
+#include "luse.h"
 
 NotifyCategoryDecl(shadowatlas, EXPORT_CLASS, EXPORT_TEMPL);
 

+ 0 - 84
direct/src/controls/GravityWalker.py

@@ -71,90 +71,6 @@ class GravityWalker(DirectObject.DirectObject):
         self.isAirborne = 0
         self.highMark = 0
 
-    """
-    def spawnTest(self):
-        assert self.notify.debugStateCall(self)
-        if not self.wantDebugIndicator:
-            return
-        from pandac.PandaModules import *
-        from direct.interval.IntervalGlobal import *
-        from toontown.coghq import MovingPlatform
-
-        if hasattr(self, "platform"):
-            # Remove the prior instantiation:
-            self.moveIval.pause()
-            del self.moveIval
-            self.platform.destroy()
-            del self.platform
-            self.platform2.destroy()
-            del self.platform2
-
-        model = loader.loadModel('phase_9/models/cogHQ/platform1')
-        fakeId = id(self)
-        self.platform = MovingPlatform.MovingPlatform()
-        self.platform.setupCopyModel(fakeId, model, 'platformcollision')
-        self.platformRoot = render.attachNewNode("GravityWalker-spawnTest-%s"%fakeId)
-        self.platformRoot.setPos(base.localAvatar, Vec3(0.0, 0.0, 1.0))
-        self.platformRoot.setHpr(base.localAvatar, Vec3.zero())
-        self.platform.reparentTo(self.platformRoot)
-
-        self.platform2 = MovingPlatform.MovingPlatform()
-        self.platform2.setupCopyModel(1+fakeId, model, 'platformcollision')
-        self.platform2Root = render.attachNewNode("GravityWalker-spawnTest2-%s"%fakeId)
-        self.platform2Root.setPos(base.localAvatar, Vec3(-16.0, 30.0, 1.0))
-        self.platform2Root.setHpr(base.localAvatar, Vec3.zero())
-        self.platform2.reparentTo(self.platform2Root)
-
-        duration = 5
-        self.moveIval = Parallel(
-                Sequence(
-                    WaitInterval(0.3),
-                    LerpPosInterval(self.platform, duration,
-                                    Vec3(0.0, 30.0, 0.0),
-                                    name='platformOut%s' % fakeId,
-                                    fluid = 1),
-                    WaitInterval(0.3),
-                    LerpPosInterval(self.platform, duration,
-                                    Vec3(0.0, 0.0, 0.0),
-                                    name='platformBack%s' % fakeId,
-                                    fluid = 1),
-                    WaitInterval(0.3),
-                    LerpPosInterval(self.platform, duration,
-                                    Vec3(0.0, 0.0, 30.0),
-                                    name='platformUp%s' % fakeId,
-                                    fluid = 1),
-                    WaitInterval(0.3),
-                    LerpPosInterval(self.platform, duration,
-                                    Vec3(0.0, 0.0, 0.0),
-                                    name='platformDown%s' % fakeId,
-                                    fluid = 1),
-                ),
-                Sequence(
-                    WaitInterval(0.3),
-                    LerpPosInterval(self.platform2, duration,
-                                    Vec3(0.0, -30.0, 0.0),
-                                    name='platform2Out%s' % fakeId,
-                                    fluid = 1),
-                    WaitInterval(0.3),
-                    LerpPosInterval(self.platform2, duration,
-                                    Vec3(0.0, 30.0, 30.0),
-                                    name='platform2Back%s' % fakeId,
-                                    fluid = 1),
-                    WaitInterval(0.3),
-                    LerpPosInterval(self.platform2, duration,
-                                    Vec3(0.0, -30.0, 0.0),
-                                    name='platform2Up%s' % fakeId,
-                                    fluid = 1),
-                    WaitInterval(0.3),
-                    LerpPosInterval(self.platform2, duration,
-                                    Vec3(0.0, 0.0, 0.0),
-                                    name='platformDown%s' % fakeId,
-                                    fluid = 1),
-                ),
-            name='platformIval%s' % fakeId,
-            )
-        self.moveIval.loop()
-    """
     def setWalkSpeed(self, forward, jump, reverse, rotate):
         assert self.notify.debugStateCall(self)
         self.avatarControlForwardSpeed=forward

+ 0 - 45
direct/src/controls/PhysicsWalker.py

@@ -67,51 +67,6 @@ class PhysicsWalker(DirectObject.DirectObject):
         self.isAirborne = 0
         self.highMark = 0
 
-    """
-    def spawnTest(self):
-        assert self.debugPrint("\n\nspawnTest()\n")
-        if not self.wantDebugIndicator:
-            return
-        from pandac.PandaModules import *
-        from direct.interval.IntervalGlobal import *
-        from toontown.coghq import MovingPlatform
-
-        if hasattr(self, "platform"):
-            # Remove the prior instantiation:
-            self.moveIval.pause()
-            del self.moveIval
-            self.platform.destroy()
-            del self.platform
-
-        model = loader.loadModel('phase_9/models/cogHQ/platform1')
-        fakeId = id(self)
-        self.platform = MovingPlatform.MovingPlatform()
-        self.platform.setupCopyModel(fakeId, model, 'platformcollision')
-        self.platformRoot = render.attachNewNode("physicsWalker-spawnTest-%s"%fakeId)
-        self.platformRoot.setPos(base.localAvatar, Vec3(0.0, 3.0, 1.0))
-        self.platformRoot.setHpr(base.localAvatar, Vec3.zero())
-        self.platform.reparentTo(self.platformRoot)
-
-        startPos = Vec3(0.0, -15.0, 0.0)
-        endPos = Vec3(0.0, 15.0, 0.0)
-        distance = Vec3(startPos-endPos).length()
-        duration = distance/4
-        self.moveIval = Sequence(
-            WaitInterval(0.3),
-            LerpPosInterval(self.platform, duration,
-                            endPos, startPos=startPos,
-                            name='platformOut%s' % fakeId,
-                            fluid = 1),
-            WaitInterval(0.3),
-            LerpPosInterval(self.platform, duration,
-                            startPos, startPos=endPos,
-                            name='platformBack%s' % fakeId,
-                            fluid = 1),
-            name='platformIval%s' % fakeId,
-            )
-        self.moveIval.loop()
-    """
-
     def setWalkSpeed(self, forward, jump, reverse, rotate):
         assert self.debugPrint("setWalkSpeed()")
         self.avatarControlForwardSpeed=forward

+ 13 - 1
direct/src/dist/commands.py

@@ -13,6 +13,7 @@ import stat
 import struct
 import imp
 import string
+import time
 
 import setuptools
 import distutils.log
@@ -30,6 +31,15 @@ if sys.version_info < (3, 0):
     # Python 3 defines these subtypes of IOError, but Python 2 doesn't.
     FileNotFoundError = IOError
 
+    # Warn the user.  They might be using Python 2 by accident.
+    print("=================================================================")
+    print("WARNING: You are using Python 2, which will soon be discontinued.")
+    print("WARNING: Please use Python 3 for best results and continued")
+    print("WARNING: support after the EOL date of December 31st, 2019.")
+    print("=================================================================")
+    sys.stdout.flush()
+    time.sleep(4.0)
+
 
 def _parse_list(input):
     if isinstance(input, basestring):
@@ -229,7 +239,9 @@ class build_apps(setuptools.Command):
         self.requirements_path = os.path.join(os.getcwd(), 'requirements.txt')
         self.use_optimized_wheels = True
         self.optimized_wheel_index = ''
-        self.pypi_extra_indexes = []
+        self.pypi_extra_indexes = [
+            'https://archive.panda3d.org/thirdparty',
+        ]
         self.file_handlers = {}
         self.exclude_dependencies = [
             # Windows

+ 14 - 5
direct/src/filter/FilterManager.py

@@ -124,7 +124,7 @@ class FilterManager(DirectObject):
 
         return winx,winy
 
-    def renderSceneInto(self, depthtex=None, colortex=None, auxtex=None, auxbits=0, textures=None):
+    def renderSceneInto(self, depthtex=None, colortex=None, auxtex=None, auxbits=0, textures=None, fbprops=None):
 
         """ Causes the scene to be rendered into the supplied textures
         instead of into the original window.  Puts a fullscreen quad
@@ -185,7 +185,10 @@ class FilterManager(DirectObject):
         # Choose the size of the offscreen buffer.
 
         (winx, winy) = self.getScaledSize(1,1,1)
-        buffer = self.createBuffer("filter-base", winx, winy, texgroup)
+        if fbprops is not None:
+            buffer = self.createBuffer("filter-base", winx, winy, texgroup, fbprops=fbprops)
+        else:
+            buffer = self.createBuffer("filter-base", winx, winy, texgroup)
 
         if (buffer == None):
             return None
@@ -236,7 +239,7 @@ class FilterManager(DirectObject):
 
         return quad
 
-    def renderQuadInto(self, name="filter-stage", mul=1, div=1, align=1, depthtex=None, colortex=None, auxtex0=None, auxtex1=None):
+    def renderQuadInto(self, name="filter-stage", mul=1, div=1, align=1, depthtex=None, colortex=None, auxtex0=None, auxtex1=None, fbprops=None):
 
         """ Creates an offscreen buffer for an intermediate
         computation. Installs a quad into the buffer.  Returns
@@ -250,7 +253,10 @@ class FilterManager(DirectObject):
 
         depthbits = bool(depthtex != None)
 
-        buffer = self.createBuffer(name, winx, winy, texgroup, depthbits)
+        if fbprops is not None:
+            buffer = self.createBuffer(name, winx, winy, texgroup, depthbits, fbprops=fbprops)
+        else:
+            buffer = self.createBuffer(name, winx, winy, texgroup, depthbits)
 
         if (buffer == None):
             return None
@@ -287,7 +293,7 @@ class FilterManager(DirectObject):
 
         return quad
 
-    def createBuffer(self, name, xsize, ysize, texgroup, depthbits=1):
+    def createBuffer(self, name, xsize, ysize, texgroup, depthbits=1, fbprops=None):
         """ Low-level buffer creation.  Not intended for public use. """
 
         winprops = WindowProperties()
@@ -297,6 +303,9 @@ class FilterManager(DirectObject):
         props.setRgbColor(1)
         props.setDepthBits(depthbits)
         props.setStereo(self.win.isStereo())
+        if fbprops is not None:
+            props.addProperties(fbprops)
+
         depthtex, colortex, auxtex0, auxtex1 = texgroup
         if (auxtex0 != None):
             props.setAuxRgba(1)

+ 18 - 3
direct/src/gui/DirectOptionMenu.py

@@ -22,10 +22,12 @@ class DirectOptionMenu(DirectButton):
             # List of items to display on the popup menu
             ('items',       [],             self.setItems),
             # Initial item to display on menu button
-            # Can be an interger index or the same string as the button
+            # Can be an integer index or the same string as the button
             ('initialitem', None,           DGG.INITOPT),
             # Amount of padding to place around popup button indicator
             ('popupMarkerBorder', (.1, .1), None),
+            # The initial position of the popup marker
+            ('popupMarker_pos', None, None),
             # Background color to use to highlight popup menu items
             ('highlightColor', (.5, .5, .5, 1), None),
             # Extra scale to use on highlight popup menu items
@@ -50,6 +52,8 @@ class DirectOptionMenu(DirectButton):
             frameSize = (-0.5, 0.5, -0.2, 0.2),
             scale = 0.4,
             relief = DGG.RAISED)
+        # Record any user specified popup marker position
+        self.initPopupMarkerPos = self['popupMarker_pos']
         # This needs to popup the menu too
         self.popupMarker.bind(DGG.B1PRESS, self.showPopupMenu)
         # Check if item is highlighted on release and select it if it is
@@ -168,8 +172,13 @@ class DirectOptionMenu(DirectButton):
         else:
             # Or base it upon largest item
             bounds = [self.minX, self.maxX, self.minZ, self.maxZ]
-        pm.setPos(bounds[1] + pmw/2.0, 0,
-                  bounds[2] + (bounds[3] - bounds[2])/2.0)
+        if self.initPopupMarkerPos:
+            # Use specified position
+            pmPos = list(self.initPopupMarkerPos)
+        else:
+            # Or base the position on the frame size.
+            pmPos = [bounds[1] + pmw/2.0, 0, bounds[2] + (bounds[3] - bounds[2])/2.0]
+        pm.setPos(pmPos[0], pmPos[1], pmPos[2])
         # Adjust popup menu button to fit all items (or use user specified
         # frame size
         bounds[1] += pmw
@@ -184,6 +193,12 @@ class DirectOptionMenu(DirectButton):
         Adjust popup position if default position puts it outside of
         visible screen region
         """
+
+        # Needed attributes (such as minZ) won't be set unless the user has specified
+        # items to display. Let's assert that we've given items to work with.
+        items = self['items']
+        assert items and len(items) > 0, 'Cannot show an empty popup menu! You must add items!'
+
         # Show the menu
         self.popupMenu.show()
         # Make sure its at the right scale

+ 6 - 4
direct/src/gui/DirectScrolledFrame.py

@@ -100,8 +100,10 @@ class DirectScrolledFrame(DirectFrame):
                 simpleChildGui = self.guiDict.get(parts[-1])
                 if simpleChildGui:
                     simpleChildGui.destroy()
-        self.verticalScroll.destroy()
-        self.horizontalScroll.destroy()
-        del self.verticalScroll
-        del self.horizontalScroll
+        if self.verticalScroll:
+            self.verticalScroll.destroy()
+        if self.horizontalScroll:
+            self.horizontalScroll.destroy()
+        self.verticalScroll = None
+        self.horizontalScroll = None
         DirectFrame.destroy(self)

+ 1 - 19
direct/src/interval/SoundInterval.py

@@ -27,8 +27,7 @@ class SoundInterval(Interval.Interval):
     # than explicitly restarting the sound every time around. This
     # prevents a skip in the sound at every repetition (the gap in
     # the sound is caused by the delay between the end of the sound
-    # and the next taskMgr cycle). There still seems to be a skip
-    # in Miles when looping MP3s. =(
+    # and the next taskMgr cycle).
     # RAU 03/01/07 add listenerNode in case we don't want to
     # use base.camera as the listener, node must not be None
     def __init__(self, sound, loop = 0, duration = 0.0, name = None,
@@ -62,23 +61,6 @@ class SoundInterval(Interval.Interval):
             #if (duration == 0):
             #    self.notify.warning('zero length duration!')
 
-            # MPG - hack for Miles bug
-            #duration += 1.5
-
-            # DCR - hack for Miles bug - adding 1.5 seconds caused
-            # problems for MG_neg_buzzer.wav
-
-            # DCR - what this is all about: Miles is under-reporting the
-            # length of MP3 files, and they're getting cut off too early.
-            # This is a temporary hack. We could:
-            # - hack Miles to fix its MP3 length calculation
-            # - complain louder about this to RAD
-            # - precompute MP3 durations and store them in a table
-
-            # drose - ok, I've put in a lower-level workaround in the
-            # MilesAudioManager.  This is no longer necessary up here,
-            # where it pollutes SoundInterval for everyone.
-            #duration += min(duration * 2.4, 1.5)
 
         # Generate unique name if necessary
         if (name == None):

+ 18 - 0
direct/src/showbase/BufferViewer.py

@@ -442,3 +442,21 @@ class BufferViewer(DirectObject):
                     cards[index] = placer
 
         return Task.cont
+
+    # Snake-case aliases, for people who prefer these.
+    advance_card = advanceCard
+    analyze_texture_set = analyzeTextureSet
+    is_enabled = isEnabled
+    is_valid_texture_set = isValidTextureSet
+    maintain_readout = maintainReadout
+    make_frame = makeFrame
+    refresh_readout = refreshReadout
+    select_card = selectCard
+    set_card_size = setCardSize
+    set_exclude = setExclude
+    set_include = setInclude
+    set_layout = setLayout
+    set_position = setPosition
+    set_render_parent = setRenderParent
+    set_sort = setSort
+    toggle_enable = toggleEnable

+ 3 - 2
direct/src/showbase/Messenger.py

@@ -624,8 +624,9 @@ class Messenger:
             for key in list(acceptorDict.keys()):
                 function, extraArgs, persistent = acceptorDict[key]
                 object = self._getObject(key)
-                if (type(object) == types.InstanceType):
-                    className = object.__class__.__name__
+                objectClass = getattr(object, '__class__', None)
+                if objectClass:
+                    className = objectClass.__name__
                 else:
                     className = "Not a class"
                 functionName = function.__name__

+ 8 - 5
direct/src/showbase/PythonUtil.py

@@ -1130,6 +1130,10 @@ def weightedChoice(choiceList, rng=random.random, sum=None):
     """given a list of (weight, item) pairs, chooses an item based on the
     weights. rng must return 0..1. if you happen to have the sum of the
     weights, pass it in 'sum'."""
+    # Throw an IndexError if we got an empty list.
+    if not choiceList:
+        raise IndexError('Cannot choose from an empty sequence')
+
     # TODO: add support for dicts
     if sum is None:
         sum = 0.
@@ -1138,6 +1142,7 @@ def weightedChoice(choiceList, rng=random.random, sum=None):
 
     rand = rng()
     accum = rand * sum
+    item = None
     for weight, item in choiceList:
         accum -= weight
         if accum <= 0.:
@@ -1652,17 +1657,15 @@ def itype(obj):
     # version of type that gives more complete information about instance types
     global dtoolSuperBase
     t = type(obj)
-    if t is types.InstanceType:
-        return '%s of <class %s>>' % (repr(types.InstanceType)[:-1],
-                                      str(obj.__class__))
+    if sys.version_info < (3, 0) and t is types.InstanceType:
+        return "<type 'instance' of <class %s>>" % (obj.__class__)
     else:
         # C++ object instances appear to be types via type()
         # check if this is a C++ object
         if dtoolSuperBase is None:
             _getDtoolSuperBase()
         if isinstance(obj, dtoolSuperBase):
-            return '%s of %s>' % (repr(types.InstanceType)[:-1],
-                                  str(obj.__class__))
+            return "<type 'instance' of %s>" % (obj.__class__)
         return t
 
 def deeptype(obj, maxLen=100, _visitedIds=None):

+ 2 - 3
direct/src/showbase/SfxPlayer.py

@@ -53,6 +53,8 @@ class SfxPlayer:
                 d = node.getDistance(listenerNode)
             else:
                 d = node.getDistance(base.cam)
+        if not cutoff:
+            cutoff = self.cutoffDistance
         if d == None or d > cutoff:
             volume = 0
         else:
@@ -70,9 +72,6 @@ class SfxPlayer:
             self, sfx, looping = 0, interrupt = 1, volume = None,
             time = 0.0, node=None, listenerNode = None, cutoff = None):
         if sfx:
-            if not cutoff:
-                cutoff = self.cutoffDistance
-
             self.setFinalVolume(sfx, node, volume, listenerNode, cutoff)
 
             # don't start over if it's already playing, unless

+ 18 - 6
direct/src/showbase/ShowBase.py

@@ -829,9 +829,11 @@ class ShowBase(DirectObject.DirectObject):
             win.requestProperties(props)
 
         mainWindow = False
-        if self.win == None:
+        if self.win is None:
             mainWindow = True
             self.win = win
+            if hasattr(self, 'bufferViewer'):
+                self.bufferViewer.win = win
 
         self.winList.append(win)
 
@@ -1677,13 +1679,19 @@ class ShowBase(DirectObject.DirectObject):
         return self.mouseWatcherNode.getModifierButtons().isDown(
             KeyboardButton.meta())
 
-    def attachInputDevice(self, device, prefix=None):
+    def attachInputDevice(self, device, prefix=None, watch=False):
         """
         This function attaches an input device to the data graph, which will
         cause the device to be polled and generate events.  If a prefix is
         given and not None, it is used to prefix events generated by this
         device, separated by a hyphen.
 
+        The watch argument can be set to True (as of Panda3D 1.10.3) to set up
+        the default MouseWatcher to receive inputs from this device, allowing
+        it to be polled via mouseWatcherNode and control user interfaces.
+        Setting this to True will also make it generate unprefixed events,
+        regardless of the specified prefix.
+
         If you call this, you should consider calling detachInputDevice when
         you are done with the device or when it is disconnected.
         """
@@ -1694,13 +1702,17 @@ class ShowBase(DirectObject.DirectObject):
         idn = self.dataRoot.attachNewNode(InputDeviceNode(device, device.name))
 
         # Setup the button thrower to generate events for the device.
-        bt = idn.attachNewNode(ButtonThrower(device.name))
-        if prefix is not None:
-            bt.node().setPrefix(prefix + '-')
+        if prefix is not None or not watch:
+            bt = idn.attachNewNode(ButtonThrower(device.name))
+            if prefix is not None:
+                bt.node().setPrefix(prefix + '-')
+            self.deviceButtonThrowers.append(bt)
 
         assert self.notify.debug("Attached input device {0} with prefix {1}".format(device, prefix))
         self.__inputDeviceNodes[device] = idn
-        self.deviceButtonThrowers.append(bt)
+
+        if watch:
+            idn.node().addChild(self.mouseWatcherNode)
 
     def detachInputDevice(self, device):
         """

+ 9 - 7
direct/src/showutil/TexMemWatcher.py

@@ -786,8 +786,9 @@ class TexMemWatcher(DirectObject):
             # Look for a single rectangular hole to hold this piece.
             tp = self.findHole(tr.area, tr.w, tr.h)
             if tp:
-                texCmp = cmp(tr.w, tr.h)
-                holeCmp = cmp(tp.p[1] - tp.p[0], tp.p[3] - tp.p[2])
+                texCmp = (tr.w > tr.h) - (tr.w < tr.h)
+                holeCmp = ((tp.p[1] - tp.p[0]) > (tp.p[3] - tp.p[2])) \
+                        - ((tp.p[1] - tp.p[0]) < (tp.p[3] - tp.p[2]))
                 if texCmp != 0 and holeCmp != 0 and texCmp != holeCmp:
                     tp.rotated = True
                 tr.placements = [tp]
@@ -803,10 +804,11 @@ class TexMemWatcher(DirectObject):
             # in.
             tpList = self.findHolePieces(tr.area)
             if tpList:
-                texCmp = cmp(tr.w, tr.h)
+                texCmp = (tr.w > tr.h) - (tr.w < tr.h)
                 tr.placements = tpList
                 for tp in tpList:
-                    holeCmp = cmp(tp.p[1] - tp.p[0], tp.p[3] - tp.p[2])
+                    holeCmp = ((tp.p[1] - tp.p[0]) > (tp.p[3] - tp.p[2])) \
+                            - ((tp.p[1] - tp.p[0]) < (tp.p[3] - tp.p[2]))
                     if texCmp != 0 and holeCmp != 0 and texCmp != holeCmp:
                         tp.rotated = True
                     tp.setBitmasks(self.bitmasks)
@@ -858,11 +860,11 @@ class TexMemWatcher(DirectObject):
             # we have to squish it?
             if tw < w:
                 # We'd have to make it taller.
-                nh = min(area / tw, th)
+                nh = min(area // tw, th)
                 th = nh
             elif th < h:
                 # We'd have to make it narrower.
-                nw = min(area / th, tw)
+                nw = min(area // th, tw)
                 tw = nw
             else:
                 # Hey, we don't have to squish it after all!  Just
@@ -912,7 +914,7 @@ class TexMemWatcher(DirectObject):
             tpArea = (r - l) * (t - b)
             if tpArea >= area:
                 # we're done.
-                shorten = (tpArea - area) / (r - l)
+                shorten = (tpArea - area) // (r - l)
                 t -= shorten
                 tp.p = (l, r, b, t)
                 tp.area = (r - l) * (t - b)

+ 0 - 23
direct/src/stdpy/threading.py

@@ -201,17 +201,6 @@ class Lock(core.Mutex):
     def __init__(self, name = "PythonLock"):
         core.Mutex.__init__(self, name)
 
-    def acquire(self, blocking = True):
-        if blocking:
-            core.Mutex.acquire(self)
-            return True
-        else:
-            return core.Mutex.tryAcquire(self)
-
-    __enter__ = acquire
-
-    def __exit__(self, t, v, tb):
-        self.release()
 
 class RLock(core.ReMutex):
     """ This class provides a wrapper around Panda's ReMutex object.
@@ -221,18 +210,6 @@ class RLock(core.ReMutex):
     def __init__(self, name = "PythonRLock"):
         core.ReMutex.__init__(self, name)
 
-    def acquire(self, blocking = True):
-        if blocking:
-            core.ReMutex.acquire(self)
-            return True
-        else:
-            return core.ReMutex.tryAcquire(self)
-
-    __enter__ = acquire
-
-    def __exit__(self, t, v, tb):
-        self.release()
-
 
 class Condition(core.ConditionVarFull):
     """ This class provides a wrapper around Panda's ConditionVarFull

+ 4 - 7
direct/src/task/Task.py

@@ -388,13 +388,10 @@ class TaskManager:
     def __setupTask(self, funcOrTask, name, priority, sort, extraArgs, taskChain, appendTask, owner, uponDeath):
         if isinstance(funcOrTask, AsyncTask):
             task = funcOrTask
-        elif hasattr(funcOrTask, '__call__'):
-            task = PythonTask(funcOrTask)
-            if name is None:
-                name = getattr(funcOrTask, '__qualname__', None) or \
-                       getattr(funcOrTask, '__name__', None)
-        elif hasattr(funcOrTask, 'cr_await') or type(funcOrTask) == types.GeneratorType:
-            # It's a coroutine, or something emulating one.
+        elif hasattr(funcOrTask, '__call__') or \
+                hasattr(funcOrTask, 'cr_await') or \
+                type(funcOrTask) == types.GeneratorType:
+            # It's a function, coroutine, or something emulating a coroutine.
             task = PythonTask(funcOrTask)
             if name is None:
                 name = getattr(funcOrTask, '__qualname__', None) or \

+ 8 - 4
direct/src/tkpanels/AnimPanel.py

@@ -9,13 +9,16 @@ __all__ = ['AnimPanel', 'ActorControl']
 # Import Tkinter, Pmw, and the floater code from this directory tree.
 from direct.tkwidgets.AppShell import *
 from direct.showbase.TkGlobal import *
-import Pmw, sys
+import Pmw, sys, os
 from direct.task import Task
+from panda3d.core import Filename, getModelPath
 
 if sys.version_info >= (3, 0):
     from tkinter.simpledialog import askfloat
+    from tkinter.filedialog import askopenfilename
 else:
     from tkSimpleDialog import askfloat
+    from tkFileDialog import askopenfilename
 
 
 FRAMES = 0
@@ -273,7 +276,7 @@ class AnimPanel(AppShell):
             title = 'Load Animation',
             parent = self.component('hull')
             )
-        if (animFilename == ''):
+        if not animFilename:
             # no file selected, canceled
             return
 
@@ -369,8 +372,9 @@ class AnimPanel(AppShell):
     def destroy(self):
         # First clean up
         taskMgr.remove(self.id + '_UpdateTask')
-        self.destroyCallBack()
-        self.destroyCallBack = None
+        if self.destroyCallBack is not None:
+            self.destroyCallBack()
+            self.destroyCallBack = None
         AppShell.destroy(self)
 
 class ActorControl(Pmw.MegaWidget):

+ 40 - 31
direct/src/tkpanels/ParticlePanel.py

@@ -96,22 +96,21 @@ class ParticlePanel(AppShell):
 
         ## MENUBAR ENTRIES ##
         # FILE MENU
-        # Get a handle on the file menu so commands can be inserted
-        # before quit item
-        fileMenu = self.menuBar.component('File-menu')
-        # MRM: Need to add load and save effects methods
-        fileMenu.insert_command(
-            fileMenu.index('Quit'),
-            label = 'Load Params',
-            command = self.loadParticleEffectFromFile)
-        fileMenu.insert_command(
-            fileMenu.index('Quit'),
-            label = 'Save Params',
-            command = self.saveParticleEffectToFile)
-        fileMenu.insert_command(
-            fileMenu.index('Quit'),
-            label = 'Print Params',
-            command = lambda s = self: s.particles.printParams())
+        # Get a handle on the file menu, and delete the Quit item that AppShell
+        # created so we can add it back after adding the other items.
+        self.menuBar.deletemenuitems('File', 0, 0)
+        self.menuBar.addmenuitem('File', 'command',
+                                 label='Load Params',
+                                 command=self.loadParticleEffectFromFile)
+        self.menuBar.addmenuitem('File', 'command',
+                                 label='Save Params',
+                                 command=self.saveParticleEffectToFile)
+        self.menuBar.addmenuitem('File', 'command',
+                                 label='Print Params',
+                                 command=lambda s=self:s.particles.printParams())
+        self.menuBar.addmenuitem('File', 'command', 'Quit this application',
+                                 label='Quit',
+                                 command=self.quit)
 
         # PARTICLE MANAGER MENU
         self.menuBar.addmenu('ParticleMgr', 'ParticleMgr Operations')
@@ -215,23 +214,23 @@ class ParticlePanel(AppShell):
             ('System', 'Pool Size',
              'Max number of simultaneous particles',
              self.setSystemPoolSize,
-             1.0, 1.0),
+             1.0, 2000000, 1.0),
             ('System', 'Birth Rate',
              'Seconds between particle births',
              self.setSystemBirthRate,
-             0.0, None),
+             0.0, None, None),
             ('System', 'Litter Size',
              'Number of particle created at each birth',
              self.setSystemLitterSize,
-             1.0, 1.0),
+             1.0, 0x7fffffff, 1.0),
             ('System', 'Litter Spread',
              'Variation in litter size',
              self.setSystemLitterSpread,
-             0.0, 1.0),
+             0.0, 0x7fffffff, 1.0),
             ('System', 'Lifespan',
              'Age in seconds at which the system (vs. particles) should die',
              self.setSystemLifespan,
-             0.0, None)
+             0.0, None, None)
             )
         self.createFloaters(systemPage, systemFloaterDefs)
 
@@ -270,27 +269,27 @@ class ParticlePanel(AppShell):
             ('Factory', 'Life Span',
              'Average particle lifespan in seconds',
              self.setFactoryLifeSpan,
-             0.0, None),
+             0.0, None, None),
             ('Factory', 'Life Span Spread',
              'Variation in lifespan',
              self.setFactoryLifeSpanSpread,
-             0.0, None),
+             0.0, None, None),
             ('Factory', 'Mass',
              'Average particle mass',
              self.setFactoryParticleMass,
-             0.001, None),
+             0.001, None, None),
             ('Factory', 'Mass Spread',
              'Variation in particle mass',
              self.setFactoryParticleMassSpread,
-             0.0, None),
+             0.0, None, None),
             ('Factory', 'Terminal Velocity',
              'Cap on average particle velocity',
              self.setFactoryTerminalVelocity,
-             0.0, None),
+             0.0, None, None),
             ('Factory', 'Terminal Vel. Spread',
              'Variation in terminal velocity',
              self.setFactoryTerminalVelocitySpread,
-             0.0, None),
+             0.0, None, None),
         )
         self.createFloaters(factoryPage, factoryWidgets)
 
@@ -967,19 +966,29 @@ class ParticlePanel(AppShell):
 
     def createFloaters(self, parent, widgetDefinitions):
         widgets = []
-        for category, label, balloonHelp, command, min, resolution in widgetDefinitions:
+        for category, label, balloonHelp, command, min, max, resolution in widgetDefinitions:
             widgets.append(
                 self.createFloater(parent, category, label, balloonHelp,
-                                   command, min, resolution)
+                                   command, min, max, resolution)
                 )
         return widgets
 
     def createFloater(self, parent, category, text, balloonHelp,
-                      command = None, min = 0.0, resolution = None,
-                      numDigits = 3, **kw):
+                      command = None, min = 0.0, max = None, resolution = None,
+                      numDigits = None, **kw):
         kw['text'] = text
         kw['min'] = min
+        if max is not None:
+            kw['max'] = max
         kw['resolution'] = resolution
+        if numDigits is None:
+            # If this is apparently an integer setting, show no decimals.
+            if resolution is not None and int(resolution) == resolution and \
+                (min is None or int(min) == min) and \
+                (max is None or int(max) == max):
+                numDigits = 0
+            else:
+                numDigits = 3
         kw['numDigits'] = numDigits
         widget = Floater.Floater(parent, **kw)
         # Do this after the widget so command isn't called on creation

+ 32 - 17
direct/src/tkwidgets/Valuator.py

@@ -656,25 +656,35 @@ def rgbPanel(nodePath, callback = None, style = 'mini'):
     pButton.pack(expand = 1, fill = BOTH)
 
     # Update menu
-    menu = vgp.component('menubar').component('Valuator Group-menu')
+    menubar = vgp.component('menubar')
+    menubar.deletemenuitems('Valuator Group', 1, 1)
+
     # Some helper functions
     # Clear color
-    menu.insert_command(index = 1, label = 'Clear Color',
-                        command = lambda: nodePath.clearColor())
+    menubar.addmenuitem(
+        'Valuator Group', 'command',
+        label='Clear Color', command=lambda: nodePath.clearColor())
     # Set Clear Transparency
-    menu.insert_command(index = 2, label = 'Set Transparency',
-                        command = lambda: nodePath.setTransparency(1))
-    menu.insert_command(
-        index = 3, label = 'Clear Transparency',
-        command = lambda: nodePath.clearTransparency())
+    menubar.addmenuitem(
+        'Valuator Group', 'command',
+        label='Set Transparency', command=lambda: nodePath.setTransparency(1))
+    menubar.addmenuitem(
+        'Valuator Group', 'command',
+        label='Clear Transparency', command=lambda: nodePath.clearTransparency())
 
 
     # System color picker
-    menu.insert_command(index = 4, label = 'Popup Color Picker',
-                        command = popupColorPicker)
+    menubar.addmenuitem(
+        'Valuator Group', 'command',
+        label='Popup Color Picker', command=popupColorPicker)
+
+    menubar.addmenuitem(
+        'Valuator Group', 'command',
+        label='Print to log', command=printToLog)
 
-    menu.insert_command(index = 5, label = 'Print to log',
-                        command = printToLog)
+    menubar.addmenuitem(
+        'Valuator Group', 'command', 'Dismiss Valuator Group panel',
+        label='Dismiss', command=vgp.destroy)
 
     def setNodePathColor(color):
         nodePath.setColor(color[0]/255.0, color[1]/255.0,
@@ -724,18 +734,23 @@ def lightRGBPanel(light, style = 'mini'):
     # Update menu button
     vgp.component('menubar').component('Valuator Group-button')['text'] = (
         'Light Control Panel')
+
     # Add a print button which will also serve as a color tile
     pButton = Button(vgp.interior(), text = 'Print to Log',
                      bg = getTkColorString(initColor),
                      command = printToLog)
     pButton.pack(expand = 1, fill = BOTH)
+
     # Update menu
-    menu = vgp.component('menubar').component('Valuator Group-menu')
+    menubar = vgp.component('menubar')
     # System color picker
-    menu.insert_command(index = 4, label = 'Popup Color Picker',
-                        command = popupColorPicker)
-    menu.insert_command(index = 5, label = 'Print to log',
-                        command = printToLog)
+    menubar.addmenuitem(
+        'Valuator Group', 'command',
+        label='Popup Color Picker', command=popupColorPicker)
+    menubar.addmenuitem(
+        'Valuator Group', 'command',
+        label='Print to log', command=printToLog)
+
     def setLightColor(color):
         light.setColor(Vec4(color[0]/255.0, color[1]/255.0,
                             color[2]/255.0, color[3]/255.0))

+ 0 - 108
dmodels/src/level_editor/donaldsDockColors.txt

@@ -1,108 +0,0 @@
-corniceColor: Vec4(0.11, 0.80, 0.22, 1.0)
-corniceColor: Vec4(0.21, 0.73, 0.31, 1.0)
-corniceColor: Vec4(0.22, 0.96, 0.27, 1.0)
-corniceColor: Vec4(0.57, 0.39, 0.34, 1.0)
-corniceColor: Vec4(0.59, 1.00, 0.92, 1.0)
-corniceColor: Vec4(0.66, 1.00, 0.86, 1.0)
-corniceColor: Vec4(0.73, 0.51, 0.51, 1.0)
-corniceColor: Vec4(0.75, 0.45, 0.45, 1.0)
-corniceColor: Vec4(0.76, 0.57, 0.29, 1.0)
-corniceColor: Vec4(0.76, 0.73, 0.64, 1.0)
-corniceColor: Vec4(0.82, 0.91, 0.44, 1.0)
-corniceColor: Vec4(0.90, 0.56, 0.34, 1.0)
-corniceColor: Vec4(0.91, 0.54, 0.44, 1.0)
-corniceColor: Vec4(0.91, 0.63, 0.44, 1.0)
-corniceColor: Vec4(0.94, 0.35, 0.35, 1.0)
-corniceColor: Vec4(0.94, 0.72, 0.66, 1.0)
-corniceColor: Vec4(1.00, 0.42, 0.27, 1.0)
-corniceColor: Vec4(1.00, 0.50, 0.38, 1.0)
-corniceColor: Vec4(1.00, 0.69, 0.49, 1.0)
-corniceColor: Vec4(1.00, 0.71, 0.27, 1.0)
-corniceColor: Vec4(1.00, 0.84, 0.59, 1.0)
-corniceColor: Vec4(1.00, 0.88, 0.80, 1.0)
-corniceColor: Vec4(1.00, 0.92, 0.59, 1.0)
-corniceColor: Vec4(1.00, 1.00, 0.59, 1.0)
-
-doorColor: Vec4(0.45, 0.53, 0.45, 1.0)
-doorColor: Vec4(0.52, 0.61, 0.52, 1.0)
-doorColor: Vec4(0.60, 0.67, 0.54, 1.0)
-doorColor: Vec4(0.63, 0.48, 0.34, 1.0)
-doorColor: Vec4(0.79, 0.47, 0.47, 1.0)
-doorColor: Vec4(0.86, 0.48, 0.23, 1.0)
-doorColor: Vec4(0.88, 0.43, 0.43, 1.0)
-doorColor: Vec4(0.91, 0.34, 0.34, 1.0)
-doorColor: Vec4(0.94, 0.70, 0.49, 1.0)
-doorColor: Vec4(0.97, 0.55, 0.40, 1.0)
-doorColor: Vec4(1.00, 0.59, 0.59, 1.0)
-
-wallColor: Vec4(0.17, 0.44, 0.28, 1.0)
-wallColor: Vec4(0.17, 0.45, 0.23, 1.0)
-wallColor: Vec4(0.36, 0.45, 0.22, 1.0)
-wallColor: Vec4(0.38, 0.31, 0.19, 1.0)
-wallColor: Vec4(0.38, 0.68, 0.46, 1.0)
-wallColor: Vec4(0.42, 0.16, 0.16, 1.0)
-wallColor: Vec4(0.42, 0.25, 0.25, 1.0)
-wallColor: Vec4(0.44, 0.67, 0.45, 1.0)
-wallColor: Vec4(0.45, 0.31, 0.17, 1.0)
-wallColor: Vec4(0.48, 0.93, 0.74, 1.0)
-wallColor: Vec4(0.52, 0.96, 0.79, 1.0)
-wallColor: Vec4(0.57, 0.70, 0.35, 1.0)
-wallColor: Vec4(0.63, 0.47, 0.24, 1.0)
-wallColor: Vec4(0.63, 0.60, 0.40, 1.0)
-wallColor: Vec4(0.64, 0.24, 0.32, 1.0)
-wallColor: Vec4(0.71, 0.49, 0.35, 1.0)
-wallColor: Vec4(0.75, 0.45, 0.45, 1.0)
-wallColor: Vec4(0.81, 0.48, 0.48, 1.0)
-wallColor: Vec4(0.87, 0.61, 0.61, 1.0)
-wallColor: Vec4(0.87, 0.69, 0.42, 1.0)
-wallColor: Vec4(0.91, 0.54, 0.54, 1.0)
-wallColor: Vec4(0.92, 0.63, 0.42, 1.0)
-wallColor: Vec4(0.93, 0.15, 0.15, 1.0)
-wallColor: Vec4(1.00, 0.00, 0.00, 1.0)
-
-windowColor: Vec4(0.00, 0.53, 0.32, 1.0)
-windowColor: Vec4(0.00, 0.61, 0.36, 1.0)
-windowColor: Vec4(0.07, 0.47, 0.31, 1.0)
-windowColor: Vec4(0.08, 0.47, 0.31, 1.0)
-windowColor: Vec4(0.17, 0.64, 0.45, 1.0)
-windowColor: Vec4(0.50, 0.38, 0.22, 1.0)
-windowColor: Vec4(0.64, 0.93, 0.45, 1.0)
-windowColor: Vec4(0.69, 0.44, 0.15, 1.0)
-windowColor: Vec4(0.73, 0.46, 0.37, 1.0)
-windowColor: Vec4(0.73, 0.63, 0.37, 1.0)
-windowColor: Vec4(0.73, 0.63, 0.45, 1.0)
-windowColor: Vec4(0.74, 0.55, 0.32, 1.0)
-windowColor: Vec4(0.78, 0.49, 0.29, 1.0)
-windowColor: Vec4(0.79, 0.47, 0.47, 1.0)
-windowColor: Vec4(0.82, 0.82, 0.40, 1.0)
-windowColor: Vec4(0.87, 0.55, 0.33, 1.0)
-windowColor: Vec4(0.87, 0.65, 0.33, 1.0)
-windowColor: Vec4(0.88, 0.43, 0.43, 1.0)
-windowColor: Vec4(0.91, 0.34, 0.45, 1.0)
-windowColor: Vec4(1.00, 0.50, 0.38, 1.0)
-windowColor: Vec4(1.00, 0.63, 0.38, 1.0)
-
-propColor: Vec4(0.17, 0.44, 0.28, 1.0)
-propColor: Vec4(0.17, 0.45, 0.23, 1.0)
-propColor: Vec4(0.36, 0.45, 0.22, 1.0)
-propColor: Vec4(0.38, 0.31, 0.19, 1.0)
-propColor: Vec4(0.38, 0.68, 0.46, 1.0)
-propColor: Vec4(0.42, 0.16, 0.16, 1.0)
-propColor: Vec4(0.42, 0.25, 0.25, 1.0)
-propColor: Vec4(0.44, 0.67, 0.45, 1.0)
-propColor: Vec4(0.45, 0.31, 0.17, 1.0)
-propColor: Vec4(0.48, 0.93, 0.74, 1.0)
-propColor: Vec4(0.52, 0.96, 0.79, 1.0)
-propColor: Vec4(0.57, 0.70, 0.35, 1.0)
-propColor: Vec4(0.63, 0.47, 0.24, 1.0)
-propColor: Vec4(0.63, 0.60, 0.40, 1.0)
-propColor: Vec4(0.64, 0.24, 0.32, 1.0)
-propColor: Vec4(0.71, 0.49, 0.35, 1.0)
-propColor: Vec4(0.75, 0.45, 0.45, 1.0)
-propColor: Vec4(0.81, 0.48, 0.48, 1.0)
-propColor: Vec4(0.87, 0.61, 0.61, 1.0)
-propColor: Vec4(0.87, 0.69, 0.42, 1.0)
-propColor: Vec4(0.91, 0.54, 0.54, 1.0)
-propColor: Vec4(0.92, 0.63, 0.42, 1.0)
-propColor: Vec4(0.93, 0.15, 0.15, 1.0)
-propColor: Vec4(1.00, 0.00, 0.00, 1.0)

+ 0 - 64
dmodels/src/level_editor/donaldsDockStyles.txt

@@ -1,64 +0,0 @@
-wallTexture: wall_md_blank_ur
-wallColor: Vec4(0.417323, 0.15711, 0.15711, 1.0)
-windowTexture: window_sm_square_ur
-windowColor: Vec4(0.874016, 0.654655, 0.329041, 1.0)
-corniceTexture: cornice_marble_ur
-corniceColor: Vec4(0.76378, 0.572086, 0.287541, 1.0)
-
-wallTexture: wall_sm_wood_ur
-wallColor: Vec4(0.874016, 0.610097, 0.610097, 1.0)
-windowTexture: window_sm_shuttered_ur
-windowColor: Vec4(0.874016, 0.548402, 0.329041, 1.0)
-corniceTexture: None
-corniceColor: None
-
-wallTexture: wall_sm_wood_ur
-wallColor: Vec4(0.913386, 0.540868, 0.540868, 1.0)
-windowTexture: window_porthole_ur
-windowColor: Vec4(0.0778138, 0.472441, 0.314961, 1.0)
-corniceTexture: cornice_horizontal_ur
-corniceColor: Vec4(1.0, 0.501961, 0.376471, 1.0)
-
-wallTexture: wall_sm_wood_ur
-wallColor: Vec4(0.913386, 0.540868, 0.540868, 1.0)
-windowTexture: window_porthole_ur
-windowColor: Vec4(0.0778138, 0.472441, 0.314961, 1.0)
-corniceTexture: cornice_shingles_ur
-corniceColor: Vec4(0.732283, 0.511163, 0.511163, 1.0)
-
-wallTexture: wall_md_blank_ur
-wallColor: Vec4(0.384314, 0.305635, 0.187618, 1.0)
-windowTexture: window_sm_round_ur
-windowColor: Vec4(0.779528, 0.489115, 0.293469, 1.0)
-corniceTexture: cornice_dental_ur
-corniceColor: Vec4(0.574803, 0.38771, 0.340374, 1.0)
-
-wallTexture: wall_bricks_dr
-wallColor: Vec4(0.629921, 0.471823, 0.237147, 1.0)
-windowTexture: window_sm_shuttered_ur
-windowColor: Vec4(1.0, 0.627451, 0.376471, 1.0)
-corniceTexture: None
-corniceColor: None
-
-wallTexture: wall_md_board_ur
-wallColor: Vec4(0.929134, 0.153034, 0.153034, 1.0)
-windowTexture: window_porthole_ur
-windowColor: Vec4(0.0, 0.532747, 0.317894, 1.0)
-corniceTexture: cornice_shingles_ur
-corniceColor: Vec4(0.944882, 0.715146, 0.659565, 1.0)
-
-wallTexture: wall_lg_brick_ur
-wallColor: Vec4(0.166003, 0.440945, 0.276671, 1.0)
-windowTexture: window_md_curtains_ur
-windowColor: Vec4(0.17258, 0.637795, 0.450208, 1.0)
-corniceTexture: None
-corniceColor: None
-
-wallTexture: wall_md_board_ur
-wallColor: Vec4(0.929134, 0.153034, 0.153034, 1.0)
-windowTexture: window_porthole_ur
-windowColor: Vec4(0.0, 0.532747, 0.317894, 1.0)
-corniceTexture: None
-corniceColor: None
-
-

BIN
dmodels/src/level_editor/donalds_dock_layout.flt


+ 0 - 61
dmodels/src/level_editor/minniesMelodyLandColors.txt

@@ -1,61 +0,0 @@
-corniceColor: Vec4(0.43, 0.32, 0.85, 1.0)
-corniceColor: Vec4(0.67, 0.40, 0.99, 1.0)
-corniceColor: Vec4(0.68, 0.22, 0.80, 1.0)
-corniceColor: Vec4(0.80, 0.22, 0.68, 1.0)
-corniceColor: Vec4(0.81, 0.30, 0.51, 1.0)
-corniceColor: Vec4(1.00, 1.00, 0.58, 1.0)
-
-doorColor: Vec4(0.42, 0.42, 0.85, 1.0)
-doorColor: Vec4(0.45, 0.22, 0.60, 1.0)
-doorColor: Vec4(0.49, 0.79, 1.00, 1.0)
-doorColor: Vec4(0.56, 0.80, 0.65, 1.0)
-doorColor: Vec4(0.59, 0.49, 1.00, 1.0)
-doorColor: Vec4(0.64, 0.45, 0.92, 1.0)
-doorColor: Vec4(0.65, 0.40, 0.82, 1.0)
-doorColor: Vec4(0.69, 0.33, 0.69, 1.0)
-doorColor: Vec4(0.80, 0.56, 0.65, 1.0)
-doorColor: Vec4(0.87, 0.80, 0.47, 1.0)
-doorColor: Vec4(0.97, 0.87, 0.47, 1.0)
-doorColor: Vec4(1.00, 0.42, 0.85, 1.0)
-doorColor: Vec4(1.00, 0.79, 0.49, 1.0)
-
-wallColor: Vec4(0.49, 0.69, 1.00, 1.0)
-wallColor: Vec4(0.59, 0.75, 1.00, 1.0)
-wallColor: Vec4(0.70, 0.76, 1.00, 1.0)
-wallColor: Vec4(0.80, 0.47, 0.80, 1.0)
-wallColor: Vec4(0.80, 0.80, 0.47, 1.0)
-wallColor: Vec4(0.91, 0.91, 0.54, 1.0)
-wallColor: Vec4(0.96, 0.96, 0.47, 1.0)
-wallColor: Vec4(0.96, 0.96, 0.73, 1.0)
-wallColor: Vec4(0.97, 0.36, 0.36, 1.0)
-wallColor: Vec4(0.97, 0.47, 0.67, 1.0)
-wallColor: Vec4(1.00, 0.70, 0.70, 1.0)
-wallColor: Vec4(1.00, 1.00, 1.00, 1.0)
-
-windowColor: Vec4(0.42, 0.42, 0.85, 1.0)
-windowColor: Vec4(0.45, 0.22, 0.60, 1.0)
-windowColor: Vec4(0.49, 0.79, 1.00, 1.0)
-windowColor: Vec4(0.56, 0.80, 0.65, 1.0)
-windowColor: Vec4(0.59, 0.49, 1.00, 1.0)
-windowColor: Vec4(0.64, 0.45, 0.92, 1.0)
-windowColor: Vec4(0.65, 0.40, 0.82, 1.0)
-windowColor: Vec4(0.69, 0.33, 0.69, 1.0)
-windowColor: Vec4(0.80, 0.45, 0.71, 1.0)
-windowColor: Vec4(0.80, 0.56, 0.65, 1.0)
-windowColor: Vec4(0.97, 0.87, 0.47, 1.0)
-windowColor: Vec4(1.00, 0.79, 0.49, 1.0)
-
-propColor: Vec4(0.49, 0.69, 1.00, 1.0)
-propColor: Vec4(0.59, 0.75, 1.00, 1.0)
-propColor: Vec4(0.70, 0.76, 1.00, 1.0)
-propColor: Vec4(0.80, 0.47, 0.80, 1.0)
-propColor: Vec4(0.80, 0.80, 0.47, 1.0)
-propColor: Vec4(0.91, 0.91, 0.54, 1.0)
-propColor: Vec4(0.96, 0.96, 0.47, 1.0)
-propColor: Vec4(0.96, 0.96, 0.73, 1.0)
-propColor: Vec4(0.97, 0.36, 0.36, 1.0)
-propColor: Vec4(0.97, 0.47, 0.67, 1.0)
-propColor: Vec4(1.00, 0.70, 0.70, 1.0)
-propColor: Vec4(1.00, 1.00, 1.00, 1.0)
-propColor: Vec4(0.92, 0.92, 0.92, 1.0)
-wallColor: Vec4(0.97, 0.58, 0.55, 1.0)

+ 0 - 79
dmodels/src/level_editor/minniesMelodyLandStyles.txt

@@ -1,79 +0,0 @@
-wallTexture: wall_md_bricks_ur
-wallColor: Vec4(0.59, 0.75, 1.00, 1.0)
-windowTexture: window_sm_round_ur
-windowColor: Vec4(0.45, 0.22, 0.60, 1.0)
-corniceTexture: None
-corniceColor: None
-
-wallTexture: wall_md_blank_ur
-wallColor: Vec4(0.91, 0.91, 0.54, 1.0)
-windowTexture: window_sm_square_ur
-windowColor: Vec4(0.65, 0.40, 0.82, 1.0)
-corniceTexture: cornice_curved_ur
-corniceColor: Vec4(0.68, 0.22, 0.80, 1.0)
-
-wallTexture: wall_sm_brick_pink_ur
-wallColor: Vec4(1.00, 1.00, 1.00, 1.0)
-windowTexture: window_sm_curved_ur
-windowColor: Vec4(0.49, 0.79, 1.00, 1.0)
-corniceTexture: None
-corniceColor: None
-
-wallTexture: wall_lg_rock_ur
-wallColor: Vec4(0.80, 0.47, 0.80, 1.0)
-windowTexture: window_sm_square_ur
-windowColor: Vec4(0.80, 0.56, 0.65, 1.0)
-corniceTexture: None
-corniceColor: None
-
-wallTexture: wall_lg_rock_ur
-wallColor: Vec4(0.80, 0.80, 0.47, 1.0)
-windowTexture: window_sm_square_ur
-windowColor: Vec4(0.56, 0.80, 0.65, 1.0)
-corniceTexture: cornice_marble_ur
-corniceColor: Vec4(0.80, 0.22, 0.68, 1.0)
-
-wallTexture: wall_md_blank_ur
-wallColor: Vec4(0.49, 0.69, 1.00, 1.0)
-windowTexture: window_sm_curved_ur
-windowColor: Vec4(0.59, 0.49, 1.00, 1.0)
-corniceTexture: None
-corniceColor: None
-
-wallTexture: wall_bricks_ur
-wallColor: Vec4(1.00, 0.70, 0.70, 1.0)
-windowTexture: window_md_curved_ur
-windowColor: Vec4(1.00, 0.79, 0.49, 1.0)
-corniceTexture: None
-corniceColor: None
-
-wallTexture: wall_md_blank_ur
-wallColor: Vec4(0.96, 0.96, 0.47, 1.0)
-windowTexture: window_sm_round_ur
-windowColor: Vec4(0.69, 0.33, 0.69, 1.0)
-corniceTexture: cornice_brick_ur
-corniceColor: Vec4(0.81, 0.30, 0.51, 1.0)
-
-wallTexture: wall_md_bricks_ur
-wallColor: Vec4(0.70, 0.76, 1.00, 1.0)
-windowTexture: window_porthole_ur
-windowColor: Vec4(0.42, 0.42, 0.85, 1.0)
-corniceTexture: None
-corniceColor: None
-
-wallTexture: wall_lg_brick_ur
-wallColor: Vec4(0.97, 0.47, 0.67, 1.0)
-windowTexture: window_md_curtains_ur
-windowColor: Vec4(0.64, 0.45, 0.92, 1.0)
-corniceTexture: None
-corniceColor: None
-
-wallTexture: wall_md_blank_ur
-wallColor: Vec4(0.97, 0.36, 0.36, 1.0)
-windowTexture: window_sm_curved_ur
-windowColor: Vec4(0.97, 0.87, 0.47, 1.0)
-corniceTexture: cornice_curved_ur
-corniceColor: Vec4(0.43, 0.32, 0.85, 1.0)
-
-
-

BIN
dmodels/src/level_editor/minnies_melody_land_layout.flt


+ 0 - 65
dmodels/src/level_editor/theBurrrghColors.txt

@@ -1,65 +0,0 @@
-corniceColor: Vec4(0.00, 0.34, 0.58, 1.0)
-corniceColor: Vec4(0.34, 0.90, 0.87, 1.0)
-corniceColor: Vec4(0.41, 0.58, 0.85, 1.0)
-corniceColor: Vec4(0.42, 0.98, 0.74, 1.0)
-corniceColor: Vec4(1.00, 1.00, 1.00, 1.0)
-
-doorColor: Vec4(0.00, 0.87, 0.69, 1.0)
-doorColor: Vec4(0.22, 0.83, 0.83, 1.0)
-doorColor: Vec4(0.23, 0.71, 0.84, 1.0)
-doorColor: Vec4(0.23, 0.85, 0.60, 1.0)
-doorColor: Vec4(0.24, 0.76, 0.89, 1.0)
-doorColor: Vec4(0.27, 1.00, 0.85, 1.0)
-doorColor: Vec4(0.38, 0.63, 1.00, 1.0)
-doorColor: Vec4(0.49, 0.69, 1.00, 1.0)
-doorColor: Vec4(0.49, 0.89, 1.00, 1.0)
-doorColor: Vec4(0.50, 0.64, 0.85, 1.0)
-doorColor: Vec4(0.59, 1.00, 0.92, 1.0)
-doorColor: Vec4(1.00, 1.00, 1.00, 1.0)
-
-wallColor: Vec4(0.00, 0.87, 0.69, 1.0)
-wallColor: Vec4(0.22, 0.83, 0.83, 1.0)
-wallColor: Vec4(0.23, 0.85, 0.60, 1.0)
-wallColor: Vec4(0.24, 0.76, 0.89, 1.0)
-wallColor: Vec4(0.25, 0.64, 0.91, 1.0)
-wallColor: Vec4(0.27, 1.00, 0.85, 1.0)
-wallColor: Vec4(0.38, 0.63, 1.00, 1.0)
-wallColor: Vec4(0.49, 0.69, 1.00, 1.0)
-wallColor: Vec4(0.49, 0.89, 1.00, 1.0)
-wallColor: Vec4(0.50, 0.64, 0.85, 1.0)
-wallColor: Vec4(0.59, 1.00, 0.92, 1.0)
-wallColor: Vec4(1.00, 1.00, 1.00, 1.0)
-
-windowColor: Vec4(0.00, 0.69, 0.69, 1.0)
-windowColor: Vec4(0.00, 0.87, 0.69, 1.0)
-windowColor: Vec4(0.14, 0.42, 0.85, 1.0)
-windowColor: Vec4(0.16, 0.67, 1.00, 1.0)
-windowColor: Vec4(0.20, 0.53, 0.46, 1.0)
-windowColor: Vec4(0.22, 0.83, 0.83, 1.0)
-windowColor: Vec4(0.23, 0.71, 0.84, 1.0)
-windowColor: Vec4(0.23, 0.85, 0.60, 1.0)
-windowColor: Vec4(0.24, 0.76, 0.89, 1.0)
-windowColor: Vec4(0.27, 1.00, 0.85, 1.0)
-windowColor: Vec4(0.38, 0.63, 1.00, 1.0)
-windowColor: Vec4(0.38, 0.87, 1.00, 1.0)
-windowColor: Vec4(0.49, 0.69, 1.00, 1.0)
-windowColor: Vec4(0.49, 0.89, 1.00, 1.0)
-windowColor: Vec4(0.49, 1.00, 1.00, 1.0)
-windowColor: Vec4(0.50, 0.64, 0.85, 1.0)
-windowColor: Vec4(0.59, 0.85, 0.69, 1.0)
-windowColor: Vec4(0.59, 0.92, 0.61, 1.0)
-windowColor: Vec4(0.59, 1.00, 0.92, 1.0)
-windowColor: Vec4(1.00, 1.00, 1.00, 1.0)
-
-propColor: Vec4(0.00, 0.87, 0.69, 1.0)
-propColor: Vec4(0.22, 0.83, 0.83, 1.0)
-propColor: Vec4(0.23, 0.85, 0.60, 1.0)
-propColor: Vec4(0.24, 0.76, 0.89, 1.0)
-propColor: Vec4(0.25, 0.64, 0.91, 1.0)
-propColor: Vec4(0.27, 1.00, 0.85, 1.0)
-propColor: Vec4(0.38, 0.63, 1.00, 1.0)
-propColor: Vec4(0.49, 0.69, 1.00, 1.0)
-propColor: Vec4(0.49, 0.89, 1.00, 1.0)
-propColor: Vec4(0.50, 0.64, 0.85, 1.0)
-propColor: Vec4(0.59, 1.00, 0.92, 1.0)
-propColor: Vec4(1.00, 1.00, 1.00, 1.0)

+ 0 - 90
dmodels/src/level_editor/theBurrrghStyles.txt

@@ -1,90 +0,0 @@
-wallTexture: wall_lg_brick_ur
-wallColor: Vec4(0.25, 0.64, 0.91, 1.0)
-windowTexture: window_sm_round_ur
-windowColor: Vec4(0.23, 0.71, 0.84, 1.0)
-corniceTexture: None
-corniceColor: None
-
-wallTexture: wall_md_blank_ur
-wallColor: Vec4(0.00, 0.87, 0.69, 1.0)
-windowTexture: window_sm_round_ur
-windowColor: Vec4(0.23, 0.71, 0.84, 1.0)
-corniceTexture: cornice_curved_ur
-corniceColor: Vec4(0.00, 0.34, 0.58, 1.0)
-
-wallTexture: wall_md_blank_ur
-wallColor: Vec4(0.49, 0.69, 1.00, 1.0)
-windowTexture: window_sm_curved_ur
-windowColor: Vec4(0.20, 0.53, 0.46, 1.0)
-corniceTexture: cornice_ice_ur
-corniceColor: Vec4(1.00, 1.00, 1.00, 1.0)
-
-wallTexture: wall_sm_brick_blue_ur
-wallColor: Vec4(1.00, 1.00, 1.00, 1.0)
-windowTexture: window_sm_square_ur
-windowColor: Vec4(0.49, 1.00, 1.00, 1.0)
-corniceTexture: None
-corniceColor: None
-
-wallTexture: wall_md_blank_ur
-wallColor: Vec4(0.27, 1.00, 0.85, 1.0)
-windowTexture: window_sm_square_ur
-windowColor: Vec4(0.49, 1.00, 1.00, 1.0)
-corniceTexture: None
-corniceColor: None
-
-wallTexture: wall_md_blank_ur
-wallColor: Vec4(0.49, 0.89, 1.00, 1.0)
-windowTexture: window_sm_pointed_ur
-windowColor: Vec4(0.00, 0.69, 0.69, 1.0)
-corniceTexture: cornice_ice_ur
-corniceColor: Vec4(1.00, 1.00, 1.00, 1.0)
-
-wallTexture: wall_md_bricks_ur
-wallColor: Vec4(0.50, 0.64, 0.85, 1.0)
-windowTexture: window_porthole_ur
-windowColor: Vec4(0.14, 0.42, 0.85, 1.0)
-corniceTexture: None
-corniceColor: None
-
-wallTexture: wall_md_blank_ur
-wallColor: Vec4(0.38, 0.63, 1.00, 1.0)
-windowTexture: window_porthole_ur
-windowColor: Vec4(0.14, 0.42, 0.85, 1.0)
-corniceTexture: cornice_dental_ur
-corniceColor: Vec4(0.41, 0.58, 0.85, 1.0)
-
-wallTexture: wall_bricks_ur
-wallColor: Vec4(0.23, 0.85, 0.60, 1.0)
-windowTexture: window_sm_square_ur
-windowColor: Vec4(0.59, 0.85, 0.69, 1.0)
-corniceTexture: None
-corniceColor: None
-
-wallTexture: wall_md_bricks_ur
-wallColor: Vec4(0.59, 1.00, 0.92, 1.0)
-windowTexture: window_md_curved_ur
-windowColor: Vec4(0.16, 0.67, 1.00, 1.0)
-corniceTexture: None
-corniceColor: None
-
-wallTexture: wall_md_blank_ur
-wallColor: Vec4(0.22, 0.83, 0.83, 1.0)
-windowTexture: window_sm_curved_ur
-windowColor: Vec4(0.38, 0.87, 1.00, 1.0)
-corniceTexture: cornice_ice_ur
-corniceColor: Vec4(1.00, 1.00, 1.00, 1.0)
-
-wallTexture: wall_sm_cement_blue_ur
-wallColor: Vec4(1.00, 1.00, 1.00, 1.0)
-windowTexture: window_sm_round_ur
-windowColor: Vec4(0.59, 0.92, 0.61, 1.0)
-corniceTexture: None
-corniceColor: None
-
-wallTexture: wall_bricks_ur
-wallColor: Vec4(0.24, 0.76, 0.89, 1.0)
-windowTexture: window_sm_round_ur
-windowColor: Vec4(0.59, 0.92, 0.61, 1.0)
-corniceTexture: None
-corniceColor: None

BIN
dmodels/src/level_editor/the_burrrgh_layout.flt


+ 0 - 106
dmodels/src/level_editor/toontownCentralColors.txt

@@ -1,106 +0,0 @@
-corniceColor: Vec4(0.11, 0.80, 0.22, 1.0)
-corniceColor: Vec4(0.21, 0.73, 0.31, 1.0)
-corniceColor: Vec4(0.22, 0.96, 0.27, 1.0)
-corniceColor: Vec4(0.27, 0.77, 0.42, 1.0)
-corniceColor: Vec4(0.32, 0.54, 0.36, 1.0)
-corniceColor: Vec4(0.44, 0.91, 0.63, 1.0)
-corniceColor: Vec4(0.76, 0.73, 0.64, 1.0)
-corniceColor: Vec4(0.79, 0.36, 0.19, 1.0)
-corniceColor: Vec4(0.82, 0.91, 0.44, 1.0)
-corniceColor: Vec4(0.90, 0.56, 0.34, 1.0)
-corniceColor: Vec4(0.91, 0.54, 0.44, 1.0)
-corniceColor: Vec4(0.91, 0.63, 0.44, 1.0)
-corniceColor: Vec4(0.94, 0.35, 0.35, 1.0)
-corniceColor: Vec4(0.94, 0.71, 0.66, 1.0)
-corniceColor: Vec4(0.98, 0.58, 0.42, 1.0)
-corniceColor: Vec4(1.00, 0.42, 0.27, 1.0)
-corniceColor: Vec4(1.00, 0.56, 0.21, 1.0)
-corniceColor: Vec4(1.00, 0.69, 0.49, 1.0)
-corniceColor: Vec4(1.00, 0.71, 0.27, 1.0)
-corniceColor: Vec4(1.00, 0.75, 0.38, 1.0)
-corniceColor: Vec4(1.00, 0.84, 0.59, 1.0)
-corniceColor: Vec4(1.00, 0.88, 0.80, 1.0)
-corniceColor: Vec4(1.00, 0.92, 0.59, 1.0)
-corniceColor: Vec4(1.00, 1.00, 0.59, 1.0)
-
-doorColor: Vec4(0.75, 0.79, 0.55, 1.0)
-doorColor: Vec4(0.81, 0.61, 0.48, 1.0)
-doorColor: Vec4(1.00, 0.59, 0.59, 1.0)
-doorColor: Vec4(1.00, 0.63, 0.38, 1.0)
-doorColor: Vec4(1.00, 0.87, 0.38, 1.0)
-doorColor: Vec4(1.00, 0.88, 0.56, 1.0)
-doorColor: Vec4(1.00, 0.88, 0.56, 1.0)
-
-wallColor: Vec4(0.11, 0.80, 0.22, 1.0)
-wallColor: Vec4(0.21, 0.73, 0.31, 1.0)
-wallColor: Vec4(0.22, 0.96, 0.27, 1.0)
-wallColor: Vec4(0.24, 0.79, 0.32, 1.0)
-wallColor: Vec4(0.25, 0.65, 0.29, 1.0)
-wallColor: Vec4(0.49, 0.96, 0.42, 1.0)
-wallColor: Vec4(0.76, 0.73, 0.64, 1.0)
-wallColor: Vec4(0.82, 0.91, 0.44, 1.0)
-wallColor: Vec4(0.90, 0.56, 0.34, 1.0)
-wallColor: Vec4(0.91, 0.54, 0.44, 1.0)
-wallColor: Vec4(0.91, 0.63, 0.44, 1.0)
-wallColor: Vec4(0.94, 0.35, 0.35, 1.0)
-wallColor: Vec4(0.95, 0.89, 0.17, 1.0)
-wallColor: Vec4(0.99, 0.67, 0.25, 1.0)
-wallColor: Vec4(0.99, 0.69, 0.49, 1.0)
-wallColor: Vec4(0.99, 0.89, 0.49, 1.0)
-wallColor: Vec4(1.00, 0.42, 0.27, 1.0)
-wallColor: Vec4(1.00, 0.67, 0.59, 1.0)
-wallColor: Vec4(1.00, 0.69, 0.49, 1.0)
-wallColor: Vec4(1.00, 0.71, 0.27, 1.0)
-wallColor: Vec4(1.00, 0.84, 0.59, 1.0)
-wallColor: Vec4(1.00, 0.88, 0.80, 1.0)
-wallColor: Vec4(1.00, 0.90, 0.33, 1.0)
-wallColor: Vec4(1.00, 0.92, 0.59, 1.0)
-wallColor: Vec4(1.00, 1.00, 0.59, 1.0)
-
-windowColor: Vec4(0.10, 0.59, 0.39, 1.0)
-windowColor: Vec4(0.11, 0.67, 0.33, 1.0)
-windowColor: Vec4(0.13, 0.78, 0.52, 1.0)
-windowColor: Vec4(0.14, 0.53, 0.30, 1.0)
-windowColor: Vec4(0.27, 1.00, 0.42, 1.0)
-windowColor: Vec4(0.31, 0.63, 0.37, 1.0)
-windowColor: Vec4(0.32, 0.54, 0.36, 1.0)
-windowColor: Vec4(0.32, 0.67, 0.60, 1.0)
-windowColor: Vec4(0.40, 0.61, 0.67, 1.0)
-windowColor: Vec4(0.59, 1.00, 0.49, 1.0)
-windowColor: Vec4(0.88, 0.44, 0.15, 1.0)
-windowColor: Vec4(0.91, 0.63, 0.44, 1.0)
-windowColor: Vec4(0.95, 0.89, 0.17, 1.0)
-windowColor: Vec4(0.99, 0.99, 0.49, 1.0)
-windowColor: Vec4(1.00, 0.27, 0.27, 1.0)
-windowColor: Vec4(1.00, 0.50, 0.38, 1.0)
-windowColor: Vec4(1.00, 0.59, 0.59, 1.0)
-windowColor: Vec4(1.00, 0.63, 0.30, 1.0)
-windowColor: Vec4(1.00, 0.63, 0.38, 1.0)
-windowColor: Vec4(1.00, 0.87, 0.38, 1.0)
-windowColor: Vec4(1.00, 0.92, 0.59, 1.0)
-
-propColor: Vec4(0.11, 0.80, 0.22, 1.0)
-propColor: Vec4(0.21, 0.73, 0.31, 1.0)
-propColor: Vec4(0.22, 0.96, 0.27, 1.0)
-propColor: Vec4(0.24, 0.79, 0.32, 1.0)
-propColor: Vec4(0.25, 0.65, 0.29, 1.0)
-propColor: Vec4(0.49, 0.96, 0.42, 1.0)
-propColor: Vec4(0.76, 0.73, 0.64, 1.0)
-propColor: Vec4(0.82, 0.91, 0.44, 1.0)
-propColor: Vec4(0.90, 0.56, 0.34, 1.0)
-propColor: Vec4(0.91, 0.54, 0.44, 1.0)
-propColor: Vec4(0.91, 0.63, 0.44, 1.0)
-propColor: Vec4(0.94, 0.35, 0.35, 1.0)
-propColor: Vec4(0.95, 0.89, 0.17, 1.0)
-propColor: Vec4(0.99, 0.67, 0.25, 1.0)
-propColor: Vec4(0.99, 0.69, 0.49, 1.0)
-propColor: Vec4(0.99, 0.89, 0.49, 1.0)
-propColor: Vec4(1.00, 0.42, 0.27, 1.0)
-propColor: Vec4(1.00, 0.67, 0.59, 1.0)
-propColor: Vec4(1.00, 0.69, 0.49, 1.0)
-propColor: Vec4(1.00, 0.71, 0.27, 1.0)
-propColor: Vec4(1.00, 0.84, 0.59, 1.0)
-propColor: Vec4(1.00, 0.88, 0.80, 1.0)
-propColor: Vec4(1.00, 0.90, 0.33, 1.0)
-propColor: Vec4(1.00, 0.92, 0.59, 1.0)
-propColor: Vec4(1.00, 1.00, 0.59, 1.0)

+ 0 - 84
dmodels/src/level_editor/toontownCentralStyles.txt

@@ -1,84 +0,0 @@
-wallTexture: wall_md_pillars_ur
-wallColor: Vec4(1.0, 0.917, 0.592, 1.0)
-windowTexture: window_sm_pointed_ur
-windowColor: Vec4(0.396,  0.611,  0.666,  1.0)
-corniceTexture: cornice_stone_ur
-corniceColor: Vec4(1.0, 1.0, 0.592,  1.0)
-
-wallTexture: wall_md_pillars_ur
-wallColor: Vec4(1.0, 1.0, 0.592157, 1.0)
-windowTexture: window_sm_pointed_ur
-windowColor: Vec4(0.142751, 0.527559, 0.295847, 1.0)
-corniceTexture: cornice_stone_ur
-corniceColor: Vec4(1.0, 1.0, 0.592157, 1.0)
-        
-wallTexture: wall_lg_brick_ur
-wallColor: Vec4(1.0, 0.415686, 0.270588, 1.0)
-windowTexture: window_porthole_ur
-windowColor: Vec4(0.306315, 0.627451, 0.370542, 1.0)
-corniceTexture: None
-corniceColor: None
-        
-wallTexture: wall_sm_cement_ur
-wallColor: Vec4(1.0, 0.882353, 0.803922, 1.0)
-windowTexture: window_porthole_ur
-windowColor: Vec4(0.0972673, 0.590551, 0.393701, 1.0)
-corniceTexture: None
-corniceColor: None
-
-wallTexture: wall_md_dental_ur
-wallColor: Vec4(0.996078, 0.894118, 0.486275, 1.0)
-windowTexture: window_md_curved_ur
-windowColor: Vec4(1.0, 0.87451, 0.376471, 1.0)
-corniceTexture: None
-corniceColor: None
-        
-wallTexture: wall_md_pillars_ur
-wallColor: Vec4(0.996078, 0.690196, 0.486275, 1.0)
-windowTexture: window_porthole_ur
-windowColor: Vec4(0.31706, 0.535433, 0.361155, 1.0)
-corniceTexture: None
-corniceColor: None
-        
-wallTexture: wall_md_pillars_ur
-wallColor: Vec4(0.996078, 0.690196, 0.486275, 1.0)
-windowTexture: window_porthole_ur
-windowColor: Vec4(0.31706, 0.535433, 0.361155, 1.0)
-corniceTexture: cornice_brick_ur
-corniceColor: Vec4(0.31706, 0.535433, 0.361155, 1.0)
-
-wallTexture: wall_lg_brick_ur
-wallColor: Vec4(0.996078, 0.690196, 0.486275, 1.0)
-windowTexture: window_sm_curved_ur
-windowColor: Vec4(0.996078, 0.996078, 0.486275, 1.0)
-corniceTexture: None
-corniceColor: None
-
-wallTexture: wall_md_blank_ur
-wallColor: Vec4(1.0, 0.415686, 0.270588, 1.0)
-windowTexture: window_sm_curved_ur
-windowColor: Vec4(1.0, 0.87451, 0.376471, 1.0)
-corniceTexture: cornice_marble_ur
-corniceColor: Vec4(1.0, 0.74902, 0.376471, 1.0)
-
-wallTexture: wall_sm_brick_ur
-wallColor: Vec4(1.0, 0.67451, 0.592157, 1.0)
-windowTexture: window_sm_pointed_ur
-windowColor: Vec4(0.88189, 0.439216, 0.145252, 1.0)
-corniceTexture: None
-corniceColor: None
-
-wallTexture: wall_md_blank_ur
-wallColor: Vec4(1.0, 0.705882, 0.270588, 1.0)
-windowTexture: window_sm_pointed_ur
-windowColor: Vec4(0.110236, 0.669291, 0.333333, 1.0)
-corniceTexture: cornice_stone_ur
-corniceColor: Vec4(0.944882, 0.711441, 0.559518, 1.0)
-
-wallTexture: wall_md_dental_ur
-wallColor: Vec4(0.909804, 0.630415, 0.444156, 1.0)
-windowTexture: window_sm_round_ur
-windowColor: Vec4(1.0, 0.270588, 0.270588, 1.0)
-corniceTexture: None
-corniceColor: None
-

BIN
dmodels/src/level_editor/toontown_central_layout.flt


+ 62 - 0
doc/ReleaseNotes

@@ -1,3 +1,65 @@
+------------------------  RELEASE 1.10.3  -----------------------
+
+This is another bugfix release that addresses a variety of issues
+in 1.10.2 and further improves the stability.
+
+* Fix crash when unplugging certain devices on macOS
+* Fix crash on macOS when using RIME input
+* Fix logging issues/crashes in apps deployed with Python 2.7
+* Fix issues when starting in fullscreen on Linux/X11
+* Fix mapping of several gamepads including Trust GXT 24
+* Fix Linux crash when no input devices are present
+* Unbreak support for matrix arrays in vertex data in OpenGL
+* Allow creating multisample FBO in OpenGL with non-MS host window
+* Support playing and looping compressed Ogg and WAV audio files
+* Fix generation of CollisionBox for transformed geometry in .egg
+* Fix Bullet rigid body transform not updating after reparenting
+* Fix sporadic color scales with lighting and custom GLSL shader
+* Prevent faulty shaders from shutting down GSG on some drivers
+* Allow None as either argument to OdeJoint.attach()
+* Fix BufferViewer when main window is not opened right away
+* Properly detect extension of pz/gz compressed video/audio files
+* Fix for invalid behavior of SparseArray methods to clear bits
+* FilterManager now allows overriding framebuffer properties
+* Fix detection of core-only OpenGL profile on some drivers
+* Add gl-forward-compatible config var for OpenGL context creation
+* Add paste-emit-keystrokes variable to disable Ctrl+V on Windows
+* Fix in-place |= operator on Panda types (such as SparseArray)
+* Fix rare FFmpeg "bad src image pointers" errors after seek
+* Fix uses of types.InstanceType in some obscure direct functions
+* Fix capsule-into-sphere collision test in degenerate case
+* KeyboardButton.ascii_key now also accepts a str character
+* Fix errors in various Tkinter DIRECT widgets
+* Expose save_egg_file/save_egg_data functions in Python API
+* Fix assertion error in BoundingBox.set_min_max
+* Fix typo in CollisionTraverser.respect_prev_transform property
+* Properly install Python bindings when building FreeBSD installer
+
+------------------------  RELEASE 1.10.2  -----------------------
+
+This release fixes several more bugs, including a few regressions
+in 1.10.1.  Upgrading is highly recommended.
+
+* Fix regression on Windows causing freezes and instability
+* Fix a memory leak issue in Python applications
+* Fix crash reading unaligned float4 column in GeomVertexReader
+* Fixes for switching to fullscreen at runtime on Windows and Linux
+* Fix incorrect display mode listing in some Linux distributions
+* Fix threading crash on Linux when using get_keyboard_map()
+* Support "from __future__ import division" for Panda types
+* Support building with Visual Studio 2019 in makepanda
+* Work around Assimp crash when loading multiple .ply models
+* On Windows, a Python 3-compatible version of Pmw is included
+* Fix ParticlePanel spam when hovering over File menu items
+* TexMemWatcher has been fixed for Python 3
+* Prevent macOS window getting stuck after base.destroy()
+* Fix assertion setting mass before shape with Bullet debug build
+* Don't error if DirectScrolledFrame is destroyed twice
+* Fix reference count corruption accessing task.__dict__
+* Fix writing to SequenceNode frame_rate property
+* Fix collider sort not copied when copying CollisionNode
+* Add OpenCollective backer file
+
 ------------------------  RELEASE 1.10.1  -----------------------
 
 This is a bugfix release intended to fix several issues in 1.10.0.

+ 0 - 47
dtool/src/dtoolbase/dllbase.txt

@@ -1,47 +0,0 @@
-; This file is used by the MSVC linker to specify DLL base addresses to
-; prevent runtime relocation of DLLs by the windows loader.  This speeds
-; loading.  This file was generated using $PANDATOOL/src/scripts/basedlls.pl
-; which uses rebase.exe from the MS platform SDK.  It may additionally be
-; hand-hacked to simplify addresses for popular dlls to aid debugging.
-
-; release dlls
-
-libpanda         0x0000000060000000 0x004c0000
-libwindisplay    0x00000000604c0000 0x00010000
-libpandadx8      0x0000000061000000 0x00090000
-libpandadx7      0x0000000061000000 0x00040000
-libpandagl       0x0000000061000000 0x00030000
-libpandaexpress  0x00000000605d0000 0x00150000
-libpandaphysics  0x0000000060720000 0x00060000
-libpandafx       0x0000000060780000 0x00020000
-libdtool         0x00000000607a0000 0x00020000
-libdtoolconfig   0x00000000607c0000 0x00040000
-libpystub        0x0000000060800000 0x00010000
-libdirect        0x0000000060810000 0x00050000
-libtoontown      0x0000000060860000 0x000b0000
-; TODO put in a base for Pirates Opt 4 DLL
-libpirates       0x0000000060860000 0x000b0000
-libmiles_audio   0x0000000060910000 0x00020000
-libpandaegg      0x0000000060930000 0x00130000
-libframework     0x0000000060a60000 0x00020000
-
-; debug dlls
-
-libpanda_d       0x0000000060000000 0x007e0000
-libwindisplay_d  0x00000000607e0000 0x00020000
-libpandadx8_d    0x0000000060800000 0x000d0000
-libpandadx7_d    0x00000000608d0000 0x00060000
-libpandagl_d     0x0000000060930000 0x00040000
-libpandaexpress_d 0x0000000060970000 0x00220000
-libpandaphysics_d 0x0000000060b90000 0x000a0000
-libpandafx_d     0x0000000060c30000 0x00030000
-libdtool_d       0x0000000060c60000 0x00030000
-libdtoolconfig_d 0x0000000060c90000 0x00070000
-libpystub_d      0x0000000060d00000 0x00010000
-libdirect_d      0x0000000060d10000 0x00080000
-libtoontown_d    0x0000000060d90000 0x00130000
-; TODO put in a base for Pirates
-libpirates_d    0x0000000060d90000 0x00130000
-libmiles_audio_d 0x0000000060ec0000 0x00030000
-libpandaegg_d    0x0000000060ef0000 0x00210000
-libframework_d   0x0000000061100000 0x00030000

+ 1 - 1
dtool/src/dtoolbase/mutexWin32Impl.I

@@ -36,7 +36,7 @@ lock() {
  */
 INLINE bool MutexWin32Impl::
 try_lock() {
-  return _funcs._try_lock(_lock);
+  return (_funcs._try_lock(_lock) != 0);
 }
 
 /**

+ 96 - 43
dtool/src/dtoolutil/executionEnvironment.cxx

@@ -85,6 +85,44 @@ extern char **GLOBAL_ARGV;
 extern int GLOBAL_ARGC;
 #endif
 
+// One of the responsibilities of ExecutionEnvironment is to determine the path
+// to the binary file that contains itself (this is useful for making other
+// components able to read files relative to Panda's installation directory).
+// When built statically, this is easy - just use the main executable filename.
+// When built shared, ExecutionEnvironment will introspect the memory map of
+// the running process to look for dynamic library paths matching this list of
+// predetermined filenames (ordered most likely to least likely).
+
+#ifndef LINK_ALL_STATIC
+static const char *const libp3dtool_filenames[] = {
+#if defined(LIBP3DTOOL_FILENAMES)
+
+  // The build system is communicating the expected filename(s) for the
+  // libp3dtool dynamic library - no guesswork needed.
+  LIBP3DTOOL_FILENAMES
+
+#elif defined(WIN32_VC)
+
+#ifdef _DEBUG
+  "libp3dtool_d.dll",
+#else
+  "libp3dtool.dll",
+#endif
+
+#elif defined(__APPLE__)
+
+  "libp3dtool." PANDA_ABI_VERSION_STR ".dylib",
+  "libp3dtool.dylib",
+
+#else
+
+  "libp3dtool.so." PANDA_ABI_VERSION_STR,
+  "libp3dtool.so",
+
+#endif
+};
+#endif /* !LINK_ALL_STATIC */
+
 // Linux with GNU libc does have global argvargc variables, but we can't
 // safely access them at stat init time--at least, not in libc5. (It does seem
 // to work with glibc2, however.)
@@ -546,13 +584,14 @@ read_args() {
   // First, we need to fill in _dtool_name.  This contains the full path to
   // the p3dtool library.
 
-#ifdef WIN32_VC
-#ifdef _DEBUG
-  HMODULE dllhandle = GetModuleHandle("libp3dtool_d.dll");
-#else
-  HMODULE dllhandle = GetModuleHandle("libp3dtool.dll");
-#endif
-  if (dllhandle != 0) {
+#ifndef LINK_ALL_STATIC
+#if defined(WIN32_VC)
+  for (const char *filename : libp3dtool_filenames) {
+    if (!_dtool_name.empty()) break;
+
+    HMODULE dllhandle = GetModuleHandle(filename);
+    if (!dllhandle) continue;
+
     static const DWORD buffer_size = 1024;
     wchar_t buffer[buffer_size];
     DWORD size = GetModuleFileNameW(dllhandle, buffer, buffer_size);
@@ -562,46 +601,44 @@ read_args() {
       _dtool_name = tmp;
     }
   }
-#endif
 
-#if defined(__APPLE__)
+#elif defined(__APPLE__)
   // And on OSX we don't have procselfmaps, but some _dyld_* functions.
 
-  if (_dtool_name.empty()) {
-    uint32_t ic = _dyld_image_count();
-    for (uint32_t i = 0; i < ic; ++i) {
-      const char *buffer = _dyld_get_image_name(i);
-      const char *tail = strrchr(buffer, '/');
-      if (tail && (strcmp(tail, "/libp3dtool." PANDA_ABI_VERSION_STR ".dylib") == 0
-                || strcmp(tail, "/libp3dtool.dylib") == 0)) {
+  uint32_t ic = _dyld_image_count();
+  for (uint32_t i = 0; i < ic; ++i) {
+    if (!_dtool_name.empty()) break;
+
+    const char *buffer = _dyld_get_image_name(i);
+    if (!buffer) continue;
+    const char *tail = strrchr(buffer, '/');
+    if (!tail) continue;
+
+    for (const char *filename : libp3dtool_filenames) {
+      if (strcmp(&tail[1], filename) == 0) {
         _dtool_name = buffer;
+        break;
       }
     }
   }
-#endif
 
-#if defined(RTLD_DI_ORIGIN)
+#elif defined(RTLD_DI_ORIGIN)
   // When building with glibc/uClibc, we typically have access to RTLD_DI_ORIGIN in Unix-like operating systems.
 
   char origin[PATH_MAX + 1];
 
-  if (_dtool_name.empty()) {
-    void *dtool_handle = dlopen("libp3dtool.so." PANDA_ABI_VERSION_STR, RTLD_NOW | RTLD_NOLOAD);
+  for (const char *filename : libp3dtool_filenames) {
+    if (!_dtool_name.empty()) break;
+
+    void *dtool_handle = dlopen(filename, RTLD_NOW | RTLD_NOLOAD);
     if (dtool_handle != nullptr && dlinfo(dtool_handle, RTLD_DI_ORIGIN, origin) != -1) {
       _dtool_name = origin;
-      _dtool_name += "/libp3dtool.so." PANDA_ABI_VERSION_STR;
-    } else {
-      // Try the version of libp3dtool.so without ABI suffix.
-      dtool_handle = dlopen("libp3dtool.so", RTLD_NOW | RTLD_NOLOAD);
-      if (dtool_handle != nullptr && dlinfo(dtool_handle, RTLD_DI_ORIGIN, origin) != -1) {
-        _dtool_name = origin;
-        _dtool_name += "/libp3dtool.so";
-      }
+      _dtool_name += '/';
+      _dtool_name += filename;
     }
   }
-#endif
 
-#if !defined(RTLD_DI_ORIGIN) && defined(RTLD_DI_LINKMAP)
+#elif defined(RTLD_DI_LINKMAP)
   // On platforms without RTLD_DI_ORIGIN, we can use dlinfo with RTLD_DI_LINKMAP to get the origin of a loaded library.
   if (_dtool_name.empty()) {
     struct link_map *map;
@@ -610,16 +647,24 @@ read_args() {
 #else
     void *self = dlopen(NULL, RTLD_NOW | RTLD_NOLOAD);
 #endif
-    dlinfo(self, RTLD_DI_LINKMAP, &map);
-
-    while (map != nullptr) {
-      const char *tail = strrchr(map->l_name, '/');
-      const char *head = strchr(map->l_name, '/');
-      if (tail && head && (strcmp(tail, "/libp3dtool.so." PANDA_ABI_VERSION_STR) == 0
-                        || strcmp(tail, "/libp3dtool.so") == 0)) {
-        _dtool_name = head;
+    if (dlinfo(self, RTLD_DI_LINKMAP, &map)) {
+      while (map != nullptr) {
+        if (!_dtool_name.empty()) break;
+
+        const char *head = strchr(map->l_name, '/');
+        if (!head) continue;
+        const char *tail = strrchr(head, '/');
+        if (!tail) continue;
+
+        for (const char *filename : libp3dtool_filenames) {
+          if (strcmp(&tail[1], filename) == 0) {
+            _dtool_name = head;
+            break;
+          }
+        }
+
+        map = map->l_next;
       }
-      map = map->l_next;
     }
   }
 #endif
@@ -634,19 +679,27 @@ read_args() {
     pifstream maps("/proc/self/maps");
 #endif
     while (!maps.fail() && !maps.eof()) {
+      if (!_dtool_name.empty()) break;
+
       char buffer[PATH_MAX];
       buffer[0] = 0;
       maps.getline(buffer, PATH_MAX);
-      const char *tail = strrchr(buffer, '/');
       const char *head = strchr(buffer, '/');
-      if (tail && head && (strcmp(tail, "/libp3dtool.so." PANDA_ABI_VERSION_STR) == 0
-                        || strcmp(tail, "/libp3dtool.so") == 0)) {
-        _dtool_name = head;
+      if (!head) continue;
+      const char *tail = strrchr(head, '/');
+      if (!tail) continue;
+
+      for (const char *filename : libp3dtool_filenames) {
+        if (strcmp(&tail[1], filename) == 0) {
+          _dtool_name = head;
+          break;
+        }
       }
     }
     maps.close();
   }
 #endif
+#endif /* !LINK_ALL_STATIC */
 
   // Now, we need to fill in _binary_name.  This contains the full path to the
   // currently running executable.

+ 317 - 0
dtool/src/dtoolutil/iostream_ext.cxx

@@ -0,0 +1,317 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file iostream_ext.cxx
+ * @author rdb
+ * @date 2017-07-24
+ */
+
+#include "iostream_ext.h"
+
+#ifdef HAVE_PYTHON
+
+#ifndef CPPPARSER
+extern struct Dtool_PyTypedObject Dtool_std_istream;
+#endif
+
+/**
+ * Reads the given number of bytes from the stream, returned as bytes object.
+ * If the given size is -1, all bytes are read from the stream.
+ */
+PyObject *Extension<istream>::
+read(Py_ssize_t size) {
+  if (size < 0) {
+    return readall();
+  }
+
+  char *buffer = nullptr;
+  std::streamsize read_bytes = 0;
+
+  if (size > 0) {
+    std::streambuf *buf = _this->rdbuf();
+    nassertr(buf != nullptr, nullptr);
+
+#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
+    PyThreadState *_save;
+    Py_UNBLOCK_THREADS
+#endif
+
+    buffer = (char *)alloca((size_t)size);
+    read_bytes = buf->sgetn(buffer, (size_t)size);
+
+#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
+    Py_BLOCK_THREADS
+#endif
+  }
+
+#if PY_MAJOR_VERSION >= 3
+  return PyBytes_FromStringAndSize(buffer, read_bytes);
+#else
+  return PyString_FromStringAndSize(buffer, read_bytes);
+#endif
+}
+
+/**
+ * Reads from the underlying stream, but using at most one call.  The number
+ * of returned bytes may therefore be less than what was requested, but it
+ * will always be greater than 0 until EOF is reached.
+ */
+PyObject *Extension<istream>::
+read1(Py_ssize_t size) {
+  std::streambuf *buf = _this->rdbuf();
+  nassertr(buf != nullptr, nullptr);
+
+#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
+  PyThreadState *_save;
+  Py_UNBLOCK_THREADS
+#endif
+
+  std::streamsize avail = buf->in_avail();
+  if (avail == 0) {
+    avail = 4096;
+  }
+
+  if (size >= 0 && (std::streamsize)size < avail) {
+    avail = (std::streamsize)size;
+  }
+
+  // Don't read more than 4K at a time
+  if (avail > 4096) {
+    avail = 4096;
+  }
+
+  char *buffer = (char *)alloca(avail);
+  std::streamsize read_bytes = buf->sgetn(buffer, avail);
+
+#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
+  Py_BLOCK_THREADS
+#endif
+
+#if PY_MAJOR_VERSION >= 3
+  return PyBytes_FromStringAndSize(buffer, read_bytes);
+#else
+  return PyString_FromStringAndSize(buffer, read_bytes);
+#endif
+}
+
+/**
+ * Reads all of the bytes in the stream.
+ */
+PyObject *Extension<istream>::
+readall() {
+  std::streambuf *buf = _this->rdbuf();
+  nassertr(buf != nullptr, nullptr);
+
+#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
+  PyThreadState *_save;
+  Py_UNBLOCK_THREADS
+#endif
+
+  std::vector<unsigned char> result;
+
+  static const size_t buffer_size = 4096;
+  char buffer[buffer_size];
+
+  std::streamsize count = buf->sgetn(buffer, buffer_size);
+  while (count != 0) {
+    thread_consider_yield();
+    result.insert(result.end(), buffer, buffer + count);
+    count = buf->sgetn(buffer, buffer_size);
+  }
+
+#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
+  Py_BLOCK_THREADS
+#endif
+
+#if PY_MAJOR_VERSION >= 3
+  return PyBytes_FromStringAndSize((char *)result.data(), result.size());
+#else
+  return PyString_FromStringAndSize((char *)result.data(), result.size());
+#endif
+}
+
+/**
+ * Reads bytes into a preallocated, writable, bytes-like object, returning the
+ * number of bytes read.
+ */
+std::streamsize Extension<istream>::
+readinto(PyObject *b) {
+  std::streambuf *buf = _this->rdbuf();
+  nassertr(buf != nullptr, 0);
+
+  Py_buffer view;
+  if (PyObject_GetBuffer(b, &view, PyBUF_CONTIG) == -1) {
+    PyErr_SetString(PyExc_TypeError,
+      "write() requires a contiguous, read-write bytes-like object");
+    return 0;
+  }
+
+#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
+  PyThreadState *_save;
+  Py_UNBLOCK_THREADS
+#endif
+
+  std::streamsize count = buf->sgetn((char *)view.buf, view.len);
+
+#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
+  Py_BLOCK_THREADS
+#endif
+
+  PyBuffer_Release(&view);
+  return count;
+}
+
+/**
+ * Extracts one line up to and including the trailing newline character.
+ * Returns empty string when the end of file is reached.
+ */
+PyObject *Extension<istream>::
+readline(Py_ssize_t size) {
+  std::streambuf *buf = _this->rdbuf();
+  nassertr(buf != nullptr, nullptr);
+
+#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
+  PyThreadState *_save;
+  Py_UNBLOCK_THREADS
+#endif
+
+  std::string line;
+  int ch = buf->sbumpc();
+  while (ch != EOF && (--size) != 0) {
+    line.push_back(ch);
+    if (ch == '\n') {
+      // Here's the newline character.
+      break;
+    }
+    ch = buf->sbumpc();
+  }
+
+#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
+  Py_BLOCK_THREADS
+#endif
+
+#if PY_MAJOR_VERSION >= 3
+  return PyBytes_FromStringAndSize(line.data(), line.size());
+#else
+  return PyString_FromStringAndSize(line.data(), line.size());
+#endif
+}
+
+/**
+ * Reads all the lines at once and returns a list.  Also see the documentation
+ * for readline().
+ */
+PyObject *Extension<istream>::
+readlines(Py_ssize_t hint) {
+  PyObject *lst = PyList_New(0);
+  if (lst == nullptr) {
+    return nullptr;
+  }
+
+  PyObject *py_line = readline(-1);
+
+  if (hint < 0) {
+    while (Py_SIZE(py_line) > 0) {
+      PyList_Append(lst, py_line);
+      Py_DECREF(py_line);
+
+      py_line = readline(-1);
+    }
+  } else {
+    Py_ssize_t totchars = 0;
+    while (Py_SIZE(py_line) > 0) {
+      totchars += Py_SIZE(py_line);
+      PyList_Append(lst, py_line);
+      Py_DECREF(py_line);
+
+      if (totchars > hint) {
+        break;
+      }
+
+      py_line = readline(-1);
+    }
+  }
+
+  return lst;
+}
+
+/**
+ * Yields continuously to read all the lines from the istream.
+ */
+static PyObject *gen_next(PyObject *self) {
+  istream *stream = nullptr;
+  if (!Dtool_Call_ExtractThisPointer(self, Dtool_std_istream, (void **)&stream)) {
+    return nullptr;
+  }
+
+  PyObject *line = invoke_extension(stream).readline();
+  if (Py_SIZE(line) > 0) {
+    return line;
+  } else {
+    PyErr_SetObject(PyExc_StopIteration, nullptr);
+    return nullptr;
+  }
+}
+
+/**
+ * Iterates over the lines of the file.
+ */
+PyObject *Extension<istream>::
+__iter__(PyObject *self) {
+  return Dtool_NewGenerator(self, &gen_next);
+}
+
+/**
+ * Writes the bytes object to the stream.
+ */
+void Extension<ostream>::
+write(PyObject *b) {
+  std::streambuf *buf = _this->rdbuf();
+  nassertv(buf != nullptr);
+
+  Py_buffer view;
+  if (PyObject_GetBuffer(b, &view, PyBUF_CONTIG_RO) == -1) {
+    PyErr_SetString(PyExc_TypeError, "write() requires a contiguous buffer");
+    return;
+  }
+
+#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
+  PyThreadState *_save;
+  Py_UNBLOCK_THREADS
+  buf->sputn((const char *)view.buf, view.len);
+  Py_BLOCK_THREADS
+#else
+  buf->sputn((const char *)view.buf, view.len);
+#endif
+
+  PyBuffer_Release(&view);
+}
+
+/**
+ * Write a list of lines to the stream.  Line separators are not added, so it
+ * is usual for each of the lines provided to have a line separator at the
+ * end.
+ */
+void Extension<ostream>::
+writelines(PyObject *lines) {
+  PyObject *seq = PySequence_Fast(lines, "writelines() expects a sequence");
+  if (seq == nullptr) {
+    return;
+  }
+
+  PyObject **items = PySequence_Fast_ITEMS(seq);
+  Py_ssize_t len = PySequence_Fast_GET_SIZE(seq);
+
+  for (Py_ssize_t i = 0; i < len; ++i) {
+    write(items[i]);
+  }
+
+  Py_DECREF(seq);
+}
+
+#endif  // HAVE_PYTHON

+ 53 - 0
dtool/src/dtoolutil/iostream_ext.h

@@ -0,0 +1,53 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file iostream_ext.h
+ * @author rdb
+ * @date 2017-07-24
+ */
+
+#ifndef IOSTREAM_EXT_H
+#define IOSTREAM_EXT_H
+
+#include "dtoolbase.h"
+
+#ifdef HAVE_PYTHON
+
+#include "extension.h"
+#include <iostream>
+#include "py_panda.h"
+
+/**
+ * These classes define the extension methods for istream and ostream, which
+ * are called instead of any C++ methods with the same prototype.
+ *
+ * These are designed to allow streams to be treated as file-like objects.
+ */
+template<>
+class Extension<istream> : public ExtensionBase<istream> {
+public:
+  PyObject *read(Py_ssize_t size=-1);
+  PyObject *read1(Py_ssize_t size=-1);
+  PyObject *readall();
+  std::streamsize readinto(PyObject *b);
+
+  PyObject *readline(Py_ssize_t size=-1);
+  PyObject *readlines(Py_ssize_t hint=-1);
+  PyObject *__iter__(PyObject *self);
+};
+
+template<>
+class Extension<ostream> : public ExtensionBase<ostream> {
+public:
+  void write(PyObject *b);
+  void writelines(PyObject *lines);
+};
+
+#endif  // HAVE_PYTHON
+
+#endif  // IOSTREAM_EXT_H

+ 1 - 0
dtool/src/dtoolutil/p3dtoolutil_ext_composite.cxx

@@ -1,3 +1,4 @@
 #include "filename_ext.cxx"
 #include "globPattern_ext.cxx"
+#include "iostream_ext.cxx"
 #include "textEncoder_ext.cxx"

+ 16 - 3
dtool/src/interrogate/functionRemap.cxx

@@ -397,17 +397,25 @@ get_call_str(const string &container, const vector_string &pexprs) const {
     }
 
     // It's not possible to assign arrays in C++, we have to copy them.
-    CPPArrayType *array_type = _parameters[_first_true_parameter]._remap->get_orig_type()->as_array_type();
+    bool paren_close = false;
+    CPPType *param_type = _parameters[_first_true_parameter]._remap->get_orig_type();
+    CPPArrayType *array_type = param_type->as_array_type();
     if (array_type != nullptr) {
       call << "std::copy(" << expr << ", " << expr << " + " << *array_type->_bounds << ", ";
-    } else {
+      paren_close = true;
+    }
+    else if (TypeManager::is_pointer_to_PyObject(param_type)) {
+      call << "Dtool_Assign_PyObject(" << expr << ", ";
+      paren_close = true;
+    }
+    else {
       call << expr << " = ";
     }
 
     _parameters[_first_true_parameter]._remap->pass_parameter(call,
                     get_parameter_expr(_first_true_parameter, pexprs));
 
-    if (array_type != nullptr) {
+    if (paren_close) {
       call << ')';
     }
 
@@ -772,6 +780,11 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
     _return_value_destructor = builder.get_destructor_for(return_meat_type);
   }
 
+  if (_type == T_getter && TypeManager::is_pointer_to_PyObject(return_type)) {
+    _manage_reference_count = true;
+    _return_value_needs_management = true;
+  }
+
   // Check for a special meaning by name and signature.
   size_t first_param = 0;
   if (_has_this) {

+ 20 - 8
dtool/src/interrogate/interfaceMakerPythonNative.cxx

@@ -431,6 +431,12 @@ get_slotted_function_def(Object *obj, Function *func, FunctionRemap *remap,
     return true;
   }
 
+  if (method_name == "operator |=") {
+    def._answer_location = "nb_inplace_or";
+    def._wrapper_type = WT_inplace_binary_operator;
+    return true;
+  }
+
   if (method_name == "__ipow__") {
     def._answer_location = "nb_inplace_power";
     def._wrapper_type = WT_inplace_ternary_operator;
@@ -1690,7 +1696,6 @@ write_module_class(ostream &out, Object *obj) {
             SlottedFunctionDef def;
             def._answer_location = true_key;
             def._wrapper_type = slotted_def._wrapper_type;
-            def._min_version = 0x03000000;
             def._wrapper_name = func->_name + "_" + true_key;
             slots[true_key] = def;
           }
@@ -1886,7 +1891,9 @@ write_module_class(ostream &out, Object *obj) {
             out << "    Py_INCREF(Py_NotImplemented);\n";
             out << "    return Py_NotImplemented;\n";
           } else if (all_nonconst) {
-            out << "  if (!Dtool_Call_ExtractThisPointer_NonConst(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n";
+            out << "  if (!Dtool_Call_ExtractThisPointer_NonConst(self, Dtool_"
+                << ClassName << ", (void **)&local_this, \"" << ClassName
+                << "." << methodNameFromCppName(fname, "", false) << "\")) {\n";
             out << "    return nullptr;\n";
           } else {
             out << "  if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n";
@@ -4945,13 +4952,14 @@ write_function_instance(ostream &out, FunctionRemap *remap,
       expected_params += "NoneType";
 
     } else if (TypeManager::is_char(type)) {
-      indent(out, indent_level) << "char " << param_name << default_expr << ";\n";
+      indent(out, indent_level) << "char *" << param_name << "_str;\n";
+      indent(out, indent_level) << "Py_ssize_t " << param_name << "_len;\n";
 
-      format_specifiers += "c";
-      parameter_list += ", &" + param_name;
+      format_specifiers += "s#";
+      parameter_list += ", &" + param_name + "_str, &" + param_name + "_len";
+      extra_param_check << " && " << param_name << "_len == 1";
 
-      // extra_param_check << " && isascii(" << param_name << ")";
-      pexpr_string = "(char) " + param_name;
+      pexpr_string = param_name + "_str[0]";
       expected_params += "char";
       only_pyobjects = false;
 
@@ -5993,7 +6001,11 @@ write_function_instance(ostream &out, FunctionRemap *remap,
       indent(out, indent_level) << "}\n";
     }
 
-    return_expr = manage_return_value(out, indent_level, remap, "return_value");
+    if (TypeManager::is_pointer_to_PyObject(remap->_return_type->get_orig_type())) {
+      indent(out, indent_level) << "Py_XINCREF(return_value);\n";
+    } else {
+      return_expr = manage_return_value(out, indent_level, remap, "return_value");
+    }
     return_expr = remap->_return_type->temporary_to_return(return_expr);
   }
 

+ 1 - 1
dtool/src/interrogate/interfaceMakerPythonNative.h

@@ -121,7 +121,7 @@ private:
   public:
     std::string _answer_location;
     WrapperType _wrapper_type;
-    int _min_version;
+    int _min_version = 0;
     std::string _wrapper_name;
     std::set<FunctionRemap*> _remaps;
     bool _keep_method;

+ 6 - 3
dtool/src/interrogate/interrogate.cxx

@@ -574,6 +574,8 @@ main(int argc, char **argv) {
     the_output_include = &output_include;
   }
 
+  int status = 0;
+
   // Now output all of the wrapper functions.
   if (!output_code_filename.empty())
   {
@@ -595,6 +597,7 @@ main(int argc, char **argv) {
 
     if (output_code.fail()) {
       nout << "Unable to write to " << output_code_filename << "\n";
+      status = -1;
     } else {
       builder.write_code(output_code,the_output_include, def);
     }
@@ -609,13 +612,13 @@ main(int argc, char **argv) {
     pofstream output_data;
     output_data_filename.open_write(output_data);
 
-    if (output_data.fail())
-    {
+    if (output_data.fail()) {
       nout << "Unable to write to " << output_data_filename << "\n";
+      status = -1;
     } else {
       InterrogateDatabase::get_ptr()->write(output_data, def);
     }
   }
 
-  return (0);
+  return status;
 }

+ 13 - 0
dtool/src/interrogatedb/py_panda.I

@@ -90,6 +90,19 @@ INLINE PyObject *DtoolInstance_RichComparePointers(PyObject *v1, PyObject *v2, i
   Py_RETURN_RICHCOMPARE(cmpval, 0, op);
 }
 
+/**
+ * Utility function for assigning a PyObject pointer while managing refcounts.
+ */
+ALWAYS_INLINE void
+Dtool_Assign_PyObject(PyObject *&ptr, PyObject *value) {
+  PyObject *prev_value = ptr;
+  if (prev_value != value) {
+    Py_XINCREF(value);
+    ptr = value;
+    Py_XDECREF(prev_value);
+  }
+}
+
 /**
  * Converts the enum value to a C long.
  */

+ 2 - 0
dtool/src/interrogatedb/py_panda.h

@@ -238,6 +238,8 @@ EXPCL_PYPANDA PyObject *_Dtool_Return(PyObject *value);
 #define Dtool_Return(value) _Dtool_Return(value)
 #endif
 
+ALWAYS_INLINE void Dtool_Assign_PyObject(PyObject *&ptr, PyObject *value);
+
 /**
  * Wrapper around Python 3.4's enum library, which does not have a C API.
  */

+ 1 - 0
dtool/src/interrogatedb/py_wrappers.cxx

@@ -47,6 +47,7 @@ static void Dtool_WrapperBase_dealloc(PyObject *self) {
   Dtool_WrapperBase *wrap = (Dtool_WrapperBase *)self;
   nassertv(wrap);
   Py_XDECREF(wrap->_self);
+  Py_TYPE(self)->tp_free(self);
 }
 
 static PyObject *Dtool_WrapperBase_repr(PyObject *self) {

+ 26 - 13
dtool/src/parser-inc/iostream

@@ -1,16 +1,15 @@
-// Filename: iostream
-// Created by:  drose (12May00)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) Carnegie Mellon University.  All rights reserved.
-//
-// All use of this software is subject to the terms of the revised BSD
-// license.  You should have received a copy of this license along
-// with this source code in a file named "LICENSE."
-//
-////////////////////////////////////////////////////////////////////
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file iostream
+ * @author drose
+ * @date 2000-05-12
+ */
 
 // This file, and all the other files in this directory, aren't
 // intended to be compiled--they're just parsed by CPPParser (and
@@ -34,6 +33,9 @@ namespace std {
   __published:
     ostream(const ostream&) = delete;
 
+    __extension void write(PyObject *b);
+    __extension void writelines(PyObject *lines);
+
     void put(char c);
     void flush();
     streampos tellp();
@@ -43,10 +45,20 @@ namespace std {
   protected:
     ostream(ostream &&);
   };
+
   class istream : virtual public ios {
   __published:
     istream(const istream&) = delete;
 
+    __extension PyObject *read(Py_ssize_t size=-1);
+    __extension PyObject *read1(Py_ssize_t size=-1);
+    __extension PyObject *readall();
+    __extension std::streamsize readinto(PyObject *b);
+
+    __extension PyObject *readline(Py_ssize_t size=-1);
+    __extension PyObject *readlines(Py_ssize_t hint=-1);
+    __extension PyObject *__iter__(PyObject *self);
+
     int get();
     streampos tellg();
     void seekg(streampos pos);
@@ -55,6 +67,7 @@ namespace std {
   protected:
     istream(istream &&);
   };
+
   class iostream : public istream, public ostream {
   __published:
     iostream(const iostream&) = delete;

+ 24 - 0
dtool/src/prc/encryptStream.cxx

@@ -12,3 +12,27 @@
  */
 
 #include "encryptStream.h"
+
+#ifdef HAVE_OPENSSL
+
+/**
+ * Must be called immediately after open_read().  Decrypts the given number of
+ * bytes and checks that they match.  The amount of header bytes are added to
+ * an offset so that skipping to 0 will skip past the header.
+ *
+ * Returns true if the read magic matches the given magic, false on error.
+ */
+bool IDecryptStream::
+read_magic(const char *magic, size_t size) {
+  char *this_magic = (char *)alloca(size);
+  read(this_magic, size);
+
+  if (!fail() && (size_t)gcount() == size && memcmp(this_magic, magic, size) == 0) {
+    _buf.set_magic_length(size);
+    return true;
+  } else {
+    return false;
+  }
+}
+
+#endif

+ 3 - 0
dtool/src/prc/encryptStream.h

@@ -53,6 +53,9 @@ PUBLISHED:
   MAKE_PROPERTY(key_length, get_key_length);
   MAKE_PROPERTY(iteration_count, get_iteration_count);
 
+public:
+  bool read_magic(const char *magic, size_t size);
+
 private:
   EncryptStreamBuf _buf;
 };

+ 18 - 0
dtool/src/prc/encryptStreamBuf.I

@@ -81,3 +81,21 @@ INLINE int EncryptStreamBuf::
 get_iteration_count() const {
   return _iteration_count;
 }
+
+/**
+ * Sets the amount of the encrypted data at the beginning that are skipped
+ * when seeking back to zero.
+ */
+INLINE void EncryptStreamBuf::
+set_magic_length(size_t length) {
+  _magic_length = length;
+}
+
+/**
+ * Sets the amount of the encrypted data at the beginning that are skipped
+ * when seeking back to zero.
+ */
+INLINE size_t EncryptStreamBuf::
+get_magic_length() const {
+  return _magic_length;
+}

+ 54 - 3
dtool/src/prc/encryptStreamBuf.cxx

@@ -177,6 +177,7 @@ open_read(std::istream *source, bool owns_source, const std::string &password) {
 
   _read_overflow_buffer = new unsigned char[_read_block_size];
   _in_read_overflow_buffer = 0;
+  _finished = false;
   thread_consider_yield();
 }
 
@@ -322,6 +323,57 @@ close_write() {
   }
 }
 
+/**
+ * Implements seeking within the stream.  EncryptStreamBuf only allows seeking
+ * back to the beginning of the stream.
+ */
+std::streampos EncryptStreamBuf::
+seekoff(std::streamoff off, ios_seekdir dir, ios_openmode which) {
+  if (which != std::ios::in) {
+    // We can only do this with the input stream.
+    return -1;
+  }
+
+  if (off != 0 || dir != std::ios::beg) {
+    // We only know how to reposition to the beginning.
+    return -1;
+  }
+
+  size_t n = egptr() - gptr();
+  gbump(n);
+
+  if (_source->rdbuf()->pubseekpos(0, std::ios::in) == (std::streampos)0) {
+    int result = EVP_DecryptInit(_read_ctx, nullptr, nullptr, nullptr);
+    nassertr_always(result > 0, -1);
+
+    _source->clear();
+    _in_read_overflow_buffer = 0;
+    _finished = false;
+
+    // Skip past the header.
+    int iv_length = EVP_CIPHER_CTX_iv_length(_read_ctx);
+    _source->ignore(6 + iv_length);
+
+    // Ignore the magic bytes.
+    size_t magic_length = get_magic_length();
+    char *buffer = (char *)alloca(magic_length);
+    if (read_chars(buffer, magic_length) == magic_length) {
+      return 0;
+    }
+  }
+
+  return -1;
+}
+
+/**
+ * Implements seeking within the stream.  EncryptStreamBuf only allows seeking
+ * back to the beginning of the stream.
+ */
+std::streampos EncryptStreamBuf::
+seekpos(std::streampos pos, ios_openmode which) {
+  return seekoff(pos, std::ios::beg, which);
+}
+
 /**
  * Called by the system ostream implementation when its internal buffer is
  * filled, plus one character.
@@ -423,7 +475,7 @@ read_chars(char *start, size_t length) {
 
   do {
     // Get more bytes from the stream.
-    if (_read_ctx == nullptr) {
+    if (_read_ctx == nullptr || _finished) {
       return 0;
     }
 
@@ -439,8 +491,7 @@ read_chars(char *start, size_t length) {
     } else {
       result =
         EVP_DecryptFinal(_read_ctx, read_buffer, &bytes_read);
-      EVP_CIPHER_CTX_free(_read_ctx);
-      _read_ctx = nullptr;
+      _finished = true;
     }
 
     if (result <= 0) {

+ 9 - 0
dtool/src/prc/encryptStreamBuf.h

@@ -44,6 +44,12 @@ public:
   INLINE void set_iteration_count(int iteration_count);
   INLINE int get_iteration_count() const;
 
+  INLINE void set_magic_length(size_t length);
+  INLINE size_t get_magic_length() const;
+
+  virtual std::streampos seekoff(std::streamoff off, ios_seekdir dir, ios_openmode which);
+  virtual std::streampos seekpos(std::streampos pos, ios_openmode which);
+
 protected:
   virtual int overflow(int c);
   virtual int sync();
@@ -71,6 +77,9 @@ private:
 
   EVP_CIPHER_CTX *_write_ctx;
   size_t _write_block_size;
+
+  size_t _magic_length = 0;
+  bool _finished = false;
 };
 
 #include "encryptStreamBuf.I"

+ 25 - 1
dtool/src/prc/streamReader.I

@@ -43,7 +43,18 @@ StreamReader(const StreamReader &copy) :
 }
 
 /**
- * The copy constructor does not copy ownership of the stream.
+ * The move constructor steals ownership of the stream.
+ */
+INLINE StreamReader::
+StreamReader(StreamReader &&from) noexcept :
+  _in(from._in),
+  _owns_stream(from._owns_stream)
+{
+  from._owns_stream = false;
+}
+
+/**
+ * The copy assignment operator does not copy ownership of the stream.
  */
 INLINE void StreamReader::
 operator = (const StreamReader &copy) {
@@ -54,6 +65,19 @@ operator = (const StreamReader &copy) {
   _owns_stream = false;
 }
 
+/**
+ * The move assignment operator steals ownership of the stream.
+ */
+INLINE void StreamReader::
+operator = (StreamReader &&from) noexcept {
+  if (_owns_stream) {
+    delete _in;
+  }
+  _in = from._in;
+  _owns_stream = from._owns_stream;
+  from._owns_stream = false;
+}
+
 /**
  *
  */

+ 2 - 0
dtool/src/prc/streamReader.h

@@ -31,7 +31,9 @@ public:
 PUBLISHED:
   INLINE explicit StreamReader(std::istream *in, bool owns_stream);
   INLINE StreamReader(const StreamReader &copy);
+  INLINE StreamReader(StreamReader &&from) noexcept;
   INLINE void operator = (const StreamReader &copy);
+  INLINE void operator = (StreamReader &&from) noexcept;
   INLINE ~StreamReader();
 
   INLINE std::istream *get_istream() const;

+ 28 - 1
dtool/src/prc/streamWriter.I

@@ -51,7 +51,21 @@ StreamWriter(const StreamWriter &copy) :
 }
 
 /**
- * The copy constructor does not copy ownership of the stream.
+ * The move constructor steals ownership of the stream.
+ */
+INLINE StreamWriter::
+StreamWriter(StreamWriter &&from) noexcept :
+#ifdef HAVE_PYTHON
+  softspace(0),
+#endif
+  _out(from._out),
+  _owns_stream(from._owns_stream)
+{
+  from._owns_stream = false;
+}
+
+/**
+ * The copy assignment operator does not copy ownership of the stream.
  */
 INLINE void StreamWriter::
 operator = (const StreamWriter &copy) {
@@ -62,6 +76,19 @@ operator = (const StreamWriter &copy) {
   _owns_stream = false;
 }
 
+/**
+ * The move assignment operator steals ownership of the stream.
+ */
+INLINE void StreamWriter::
+operator = (StreamWriter &&from) noexcept {
+  if (_owns_stream) {
+    delete _out;
+  }
+  _out = from._out;
+  _owns_stream = from._owns_stream;
+  from._owns_stream = false;
+}
+
 /**
  *
  */

+ 2 - 0
dtool/src/prc/streamWriter.h

@@ -32,7 +32,9 @@ public:
 PUBLISHED:
   INLINE explicit StreamWriter(std::ostream *out, bool owns_stream);
   INLINE StreamWriter(const StreamWriter &copy);
+  INLINE StreamWriter(StreamWriter &&from) noexcept;
   INLINE void operator = (const StreamWriter &copy);
+  INLINE void operator = (StreamWriter &&from) noexcept;
   INLINE ~StreamWriter();
 
   INLINE std::ostream *get_ostream() const;

+ 2 - 2
makepanda/makepackage.py

@@ -748,7 +748,7 @@ def MakeInstallerOSX(version, runtime=False, python_versions=[], **kwargs):
     oscmd('rm -f Panda3D-rw.dmg')
 
 
-def MakeInstallerFreeBSD(version, runtime=False, **kwargs):
+def MakeInstallerFreeBSD(version, runtime=False, python_versions=[], **kwargs):
     outputdir = GetOutputDir()
 
     oscmd("rm -rf targetroot +DESC pkg-plist +MANIFEST")
@@ -758,7 +758,7 @@ def MakeInstallerFreeBSD(version, runtime=False, **kwargs):
     if runtime:
         InstallRuntime(destdir="targetroot", prefix="/usr/local", outputdir=outputdir)
     else:
-        InstallPanda(destdir="targetroot", prefix="/usr/local", outputdir=outputdir)
+        InstallPanda(destdir="targetroot", prefix="/usr/local", outputdir=outputdir, python_versions=python_versions)
 
     if not os.path.exists("/usr/sbin/pkg"):
         exit("Cannot create an installer without pkg")

+ 52 - 17
makepanda/makepanda.py

@@ -157,7 +157,7 @@ def usage(problem):
     print("  --everything      (enable every third-party lib)")
     print("  --directx-sdk=X   (specify version of DirectX SDK to use: jun2010, aug2009, mar2009, aug2006)")
     print("  --windows-sdk=X   (specify Windows SDK version, eg. 7.0, 7.1 or 10.  Default is 7.1)")
-    print("  --msvc-version=X  (specify Visual C++ version, eg. 10, 11, 12, 14.  Default is 14)")
+    print("  --msvc-version=X  (specify Visual C++ version, eg. 10, 11, 12, 14, 14.1, 14.2.  Default is 14)")
     print("  --use-icl         (experimental setting to use an intel compiler instead of MSVC on Windows)")
     print("")
     print("The simplest way to compile panda is to just type:")
@@ -554,6 +554,17 @@ if RUNTIME and not HOST_URL:
     # Set this to a nice default.
     HOST_URL = "https://runtime.panda3d.org/"
 
+if not PkgSkip("PYTHON") and SDK["PYTHONVERSION"] == "python2.7":
+    warn_prefix = "%sWARNING:%s " % (GetColor("red"), GetColor())
+    print("=========================================================================")
+    print(warn_prefix + "Python 2.7 will reach EOL after December 31, 2019, and will not")
+    print(warn_prefix + "be supported after that date.  Please ensure you are prepared")
+    print(warn_prefix + "by planning your upgrade to Python 3 now.")
+    print("=========================================================================")
+    sys.stdout.flush()
+    # Give the user some time to contemplate their sins
+    time.sleep(6.0)
+
 ########################################################################
 ##
 ## Choose a Compiler.
@@ -913,6 +924,10 @@ if (COMPILER=="GCC"):
         else:
             PkgDisable("OPENCV")
 
+        if GetTarget() == "darwin" and not PkgSkip("OPENAL"):
+            LibName("OPENAL", "-framework AudioToolbox")
+            LibName("OPENAL", "-framework CoreAudio")
+
         if not PkgSkip("ASSIMP") and \
             os.path.isfile(GetThirdpartyDir() + "assimp/lib/libassimp.a"):
             # Also pick up IrrXML, which is needed when linking statically.
@@ -998,12 +1013,26 @@ if (COMPILER=="GCC"):
 
     if GetTarget() == 'darwin':
         LibName("ALWAYS", "-framework AppKit")
+        LibName("IOKIT", "-framework IOKit")
+        LibName("QUARTZ", "-framework Quartz")
         LibName("AGL", "-framework AGL")
         LibName("CARBON", "-framework Carbon")
         LibName("COCOA", "-framework Cocoa")
         # Fix for a bug in OSX Leopard:
         LibName("GL", "-dylib_file /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib:/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib")
 
+        # Temporary exceptions to removal of this flag
+        if not PkgSkip("ROCKET"):
+            LibName("ROCKET", "-undefined dynamic_lookup")
+        if not PkgSkip("FFMPEG"):
+            LibName("FFMPEG", "-undefined dynamic_lookup")
+        if not PkgSkip("ASSIMP"):
+            LibName("ASSIMP", "-undefined dynamic_lookup")
+        if not PkgSkip("OPENEXR"):
+            LibName("OPENEXR", "-undefined dynamic_lookup")
+        if not PkgSkip("VRPN"):
+            LibName("VRPN", "-undefined dynamic_lookup")
+
     if GetTarget() == 'android':
         LibName("ALWAYS", '-llog')
         LibName("ANDROID", '-landroid')
@@ -1129,6 +1158,7 @@ def BracketNameWithQuotes(name):
     # Workaround for OSX bug - compiler doesn't like those flags quoted.
     if (name.startswith("-framework")): return name
     if (name.startswith("-dylib_file")): return name
+    if (name.startswith("-undefined ")): return name
 
     # Don't add quotes when it's not necessary.
     if " " not in name: return name
@@ -1802,9 +1832,11 @@ def CompileLink(dll, obj, opts):
                 cmd += ' -Wl,--allow-shlib-undefined'
         else:
             if (GetTarget() == "darwin"):
-                cmd = cxx + ' -undefined dynamic_lookup'
-                if ("BUNDLE" in opts or GetOrigExt(dll) == ".pyd"):
-                    cmd += ' -bundle '
+                cmd = cxx
+                if GetOrigExt(dll) == ".pyd":
+                    cmd += ' -bundle -undefined dynamic_lookup'
+                elif "BUNDLE" in opts:
+                    cmd += ' -bundle'
                 else:
                     install_name = '@loader_path/../lib/' + os.path.basename(dll)
                     cmd += ' -dynamiclib -install_name ' + install_name
@@ -2314,7 +2346,6 @@ DTOOL_CONFIG=[
     ("COMPILE_IN_DEFAULT_FONT",        '1',                      '1'),
     ("STDFLOAT_DOUBLE",                'UNDEF',                  'UNDEF'),
     ("HAVE_MAYA",                      '1',                      '1'),
-    ("HAVE_SOFTIMAGE",                 'UNDEF',                  'UNDEF'),
     ("REPORT_OPENSSL_ERRORS",          '1',                      '1'),
     ("USE_PANDAFILESTREAM",            '1',                      '1'),
     ("USE_DELETED_CHAIN",              '1',                      '1'),
@@ -2855,6 +2886,14 @@ for basename in del_files:
 p3d_init = """"Python bindings for the Panda3D libraries"
 
 __version__ = '%s'
+
+if __debug__:
+    import sys
+    if sys.version_info < (3, 0):
+        sys.stderr.write("WARNING: Python 2.7 will reach EOL after December 31, 2019.\\n")
+        sys.stderr.write("To suppress this warning, upgrade to Python 3.\\n")
+        sys.stderr.flush()
+    del sys
 """ % (WHLVERSION)
 
 if GetTarget() == 'windows':
@@ -3003,9 +3042,6 @@ else:
 if (GetTarget() == 'darwin'):
     configprc = configprc.replace("$XDG_CACHE_HOME/panda3d", "$HOME/Library/Caches/Panda3D-%s" % MAJOR_VERSION)
 
-    # OpenAL is not yet working well on OSX for us, so let's do this for now.
-    configprc = configprc.replace("p3openal_audio", "p3fmod_audio")
-
 if GetTarget() == 'windows':
     # Convert to Windows newlines.
     ConditionalWriteFile(GetOutputDir()+"/etc/Config.prc", configprc, newline='\r\n')
@@ -3654,6 +3690,7 @@ IGATEFILES += [
     "globPattern_ext.h",
     "pandaFileStream.h",
     "lineStream.h",
+    "iostream_ext.h",
 ]
 TargetAdd('libp3dtoolutil.in', opts=OPTS, input=IGATEFILES)
 TargetAdd('libp3dtoolutil.in', opts=['IMOD:panda3d.core', 'ILIB:libp3dtoolutil', 'SRCDIR:dtool/src/dtoolutil'])
@@ -3702,7 +3739,6 @@ OPTS=['DIR:panda/src/downloader', 'OPENSSL', 'ZLIB']
 IGATEFILES=GetDirectoryContents('panda/src/downloader', ["*.h", "*_composite*.cxx"])
 TargetAdd('libp3downloader.in', opts=OPTS, input=IGATEFILES)
 TargetAdd('libp3downloader.in', opts=['IMOD:panda3d.core', 'ILIB:libp3downloader', 'SRCDIR:panda/src/downloader'])
-PyTargetAdd('p3downloader_stringStream_ext.obj', opts=OPTS, input='stringStream_ext.cxx')
 
 #
 # DIRECTORY: panda/metalibs/pandaexpress/
@@ -3985,12 +4021,12 @@ if (not RUNTIME):
 #
 
 if (not RUNTIME):
-  OPTS=['DIR:panda/src/display', 'BUILDING:PANDA']
+  OPTS=['DIR:panda/src/display', 'BUILDING:PANDA', 'X11']
   TargetAdd('p3display_graphicsStateGuardian.obj', opts=OPTS, input='graphicsStateGuardian.cxx')
   TargetAdd('p3display_composite1.obj', opts=OPTS, input='p3display_composite1.cxx')
   TargetAdd('p3display_composite2.obj', opts=OPTS, input='p3display_composite2.cxx')
 
-  OPTS=['DIR:panda/src/display']
+  OPTS=['DIR:panda/src/display', 'X11']
   IGATEFILES=GetDirectoryContents('panda/src/display', ["*.h", "*_composite*.cxx"])
   IGATEFILES.remove("renderBuffer.h")
   TargetAdd('libp3display.in', opts=OPTS, input=IGATEFILES)
@@ -4209,7 +4245,7 @@ if (not RUNTIME):
   OPTS=['DIR:panda/metalibs/panda', 'BUILDING:PANDA', 'JPEG', 'PNG', 'HARFBUZZ',
       'TIFF', 'OPENEXR', 'ZLIB', 'OPENSSL', 'FREETYPE', 'FFTW', 'ADVAPI', 'WINSOCK2',
       'SQUISH', 'NVIDIACG', 'VORBIS', 'OPUS', 'WINUSER', 'WINMM', 'WINGDI', 'IPHLPAPI',
-      'SETUPAPI']
+      'SETUPAPI', 'IOKIT']
 
   TargetAdd('panda_panda.obj', opts=OPTS, input='panda.cxx')
 
@@ -4339,7 +4375,6 @@ if (not RUNTIME):
   PyTargetAdd('core.pyd', input='p3prc_ext_composite.obj')
 
   PyTargetAdd('core.pyd', input='libp3downloader_igate.obj')
-  PyTargetAdd('core.pyd', input='p3downloader_stringStream_ext.obj')
   PyTargetAdd('core.pyd', input='p3express_ext_composite.obj')
   PyTargetAdd('core.pyd', input='libp3express_igate.obj')
 
@@ -4725,7 +4760,7 @@ if not RUNTIME and not PkgSkip("EGG"):
   TargetAdd('p3egg2pg_composite2.obj', opts=OPTS, input='p3egg2pg_composite2.cxx')
 
   OPTS=['DIR:panda/src/egg2pg']
-  IGATEFILES=['load_egg_file.h']
+  IGATEFILES=['load_egg_file.h', 'save_egg_file.h']
   TargetAdd('libp3egg2pg.in', opts=OPTS, input=IGATEFILES)
   TargetAdd('libp3egg2pg.in', opts=['IMOD:panda3d.egg', 'ILIB:libp3egg2pg', 'SRCDIR:panda/src/egg2pg'])
 
@@ -4851,7 +4886,7 @@ if (GetTarget() == 'darwin' and PkgSkip("COCOA")==0 and PkgSkip("GL")==0 and not
   if (PkgSkip('PANDAFX')==0):
     TargetAdd('libpandagl.dll', input='libpandafx.dll')
   TargetAdd('libpandagl.dll', input=COMMON_PANDA_LIBS)
-  TargetAdd('libpandagl.dll', opts=['MODULE', 'GL', 'NVIDIACG', 'CGGL', 'COCOA', 'CARBON'])
+  TargetAdd('libpandagl.dll', opts=['MODULE', 'GL', 'NVIDIACG', 'CGGL', 'COCOA', 'CARBON', 'QUARTZ'])
 
 #
 # DIRECTORY: panda/src/wgldisplay/
@@ -5172,7 +5207,7 @@ if (not RUNTIME and GetTarget() == 'android'):
     TargetAdd('libppython.dll', input='libp3framework.dll')
     TargetAdd('libppython.dll', input='libp3android.dll')
     TargetAdd('libppython.dll', input=COMMON_PANDA_LIBS)
-    TargetAdd('libppython.dll', opts=['MODULE', 'ANDROID'])
+    TargetAdd('libppython.dll', opts=['MODULE', 'ANDROID', 'PYTHON'])
 
 #
 # DIRECTORY: panda/src/androiddisplay/
@@ -5197,7 +5232,7 @@ if (GetTarget() == 'android' and PkgSkip("EGL")==0 and PkgSkip("GLES")==0 and no
 #
 
 if (not RUNTIME and (GetTarget() in ('windows', 'darwin') or PkgSkip("X11")==0) and PkgSkip("TINYDISPLAY")==0):
-  OPTS=['DIR:panda/src/tinydisplay', 'BUILDING:TINYDISPLAY']
+  OPTS=['DIR:panda/src/tinydisplay', 'BUILDING:TINYDISPLAY', 'X11']
   TargetAdd('p3tinydisplay_composite1.obj', opts=OPTS, input='p3tinydisplay_composite1.cxx')
   TargetAdd('p3tinydisplay_composite2.obj', opts=OPTS, input='p3tinydisplay_composite2.cxx')
   TargetAdd('p3tinydisplay_ztriangle_1.obj', opts=OPTS, input='ztriangle_1.cxx')

+ 0 - 9
makepanda/makepanda.vcproj

@@ -2147,7 +2147,6 @@
 				<File RelativePath="..\panda\src\express\test_types.cxx"></File>
 				<File RelativePath="..\panda\src\express\weakPointerTo.I"></File>
 				<File RelativePath="..\panda\src\express\pta_int.cxx"></File>
-				<File RelativePath="..\panda\src\express\threadSafePointerToBase.I"></File>
 				<File RelativePath="..\panda\src\express\namable.I"></File>
 				<File RelativePath="..\panda\src\express\vector_float.cxx"></File>
 				<File RelativePath="..\panda\src\express\pointerTo.h"></File>
@@ -2174,7 +2173,6 @@
 				<File RelativePath="..\panda\src\express\datagramGenerator.h"></File>
 				<File RelativePath="..\panda\src\express\weakPointerToVoid.h"></File>
 				<File RelativePath="..\panda\src\express\datagram.I"></File>
-				<File RelativePath="..\panda\src\express\threadSafePointerTo.h"></File>
 				<File RelativePath="..\panda\src\express\weakPointerCallback.h"></File>
 				<File RelativePath="..\panda\src\express\datagram.h"></File>
 				<File RelativePath="..\panda\src\express\textEncoder.h"></File>
@@ -2206,7 +2204,6 @@
 				<File RelativePath="..\panda\src\express\typedReferenceCount.h"></File>
 				<File RelativePath="..\panda\src\express\virtualFileMountSystem.I"></File>
 				<File RelativePath="..\panda\src\express\nodePointerTo.I"></File>
-				<File RelativePath="..\panda\src\express\profileTimer.I"></File>
 				<File RelativePath="..\panda\src\express\hashVal.I"></File>
 				<File RelativePath="..\panda\src\express\pta_float.cxx"></File>
 				<File RelativePath="..\panda\src\express\weakPointerTo.h"></File>
@@ -2215,10 +2212,7 @@
 				<File RelativePath="..\panda\src\express\pointerToArrayBase.I"></File>
 				<File RelativePath="..\panda\src\express\datagramIterator.I"></File>
 				<File RelativePath="..\panda\src\express\vector_uchar.h"></File>
-				<File RelativePath="..\panda\src\express\profileTimer.h"></File>
 				<File RelativePath="..\panda\src\express\datagramIterator.h"></File>
-				<File RelativePath="..\panda\src\express\threadSafePointerTo.cxx"></File>
-				<File RelativePath="..\panda\src\express\profileTimer.cxx"></File>
 				<File RelativePath="..\panda\src\express\datagramGenerator.cxx"></File>
 				<File RelativePath="..\panda\src\express\hashGeneratorBase.h"></File>
 				<File RelativePath="..\panda\src\express\patchfile.cxx"></File>
@@ -2262,7 +2256,6 @@
 				<File RelativePath="..\panda\src\express\namable.cxx"></File>
 				<File RelativePath="..\panda\src\express\trueClock.I"></File>
 				<File RelativePath="..\panda\src\express\config_express.cxx"></File>
-				<File RelativePath="..\panda\src\express\threadSafePointerToBase.cxx"></File>
 				<File RelativePath="..\panda\src\express\pointerToVoid.I"></File>
 				<File RelativePath="..\panda\src\express\vector_uchar.cxx"></File>
 				<File RelativePath="..\panda\src\express\vector_float.h"></File>
@@ -2289,7 +2282,6 @@
 				<File RelativePath="..\panda\src\express\datagramGenerator.I"></File>
 				<File RelativePath="..\panda\src\express\compress_string.cxx"></File>
 				<File RelativePath="..\panda\src\express\subStreamBuf.cxx"></File>
-				<File RelativePath="..\panda\src\express\threadSafePointerToBase.h"></File>
 				<File RelativePath="..\panda\src\express\pointerToArrayBase.cxx"></File>
 				<File RelativePath="..\panda\src\express\express_composite.cxx"></File>
 				<File RelativePath="..\panda\src\express\virtualFileComposite.I"></File>
@@ -2297,7 +2289,6 @@
 				<File RelativePath="..\panda\src\express\multifile.I"></File>
 				<File RelativePath="..\panda\src\express\virtualFile.I"></File>
 				<File RelativePath="..\panda\src\express\patchfile.I"></File>
-				<File RelativePath="..\panda\src\express\threadSafePointerTo.I"></File>
 				<File RelativePath="..\panda\src\express\virtualFileList.h"></File>
 			</Filter>
 			<Filter Name="iphonedisplay">

+ 9 - 2
makepanda/makepandacore.py

@@ -78,6 +78,7 @@ MSVCVERSIONINFO = {
     (12,0): {"vsversion":(12,0), "vsname":"Visual Studio 2013"},
     (14,0): {"vsversion":(14,0), "vsname":"Visual Studio 2015"},
     (14,1): {"vsversion":(15,0), "vsname":"Visual Studio 2017"},
+    (14,2): {"vsversion":(16,0), "vsname":"Visual Studio 2019"},
 }
 
 ########################################################################
@@ -2796,8 +2797,14 @@ def SetupVisualStudioEnviron():
         elif not win_kit.endswith('\\'):
             win_kit += '\\'
 
-        AddToPathEnv("LIB", win_kit + "Lib\\10.0.10150.0\\ucrt\\" + arch)
-        AddToPathEnv("INCLUDE", win_kit + "Include\\10.0.10150.0\\ucrt")
+        for vnum in 10150, 10240, 10586, 14393, 15063, 16299, 17134, 17763:
+            version = "10.0.{0}.0".format(vnum)
+            if os.path.isfile(win_kit + "Include\\" + version + "\\ucrt\\assert.h"):
+                print("Using Universal CRT %s" % (version))
+                break
+
+        AddToPathEnv("LIB", "%s\\Lib\\%s\\ucrt\\%s" % (win_kit, version, arch))
+        AddToPathEnv("INCLUDE", "%s\\Include\\%s\\ucrt" % (win_kit, version))
 
         # Copy the DLLs to the bin directory.
         CopyAllFiles(GetOutputDir() + "/bin/", win_kit + "Redist\\ucrt\\DLLs\\" + arch + "\\")

+ 15 - 2
makepanda/makewheel.py

@@ -596,10 +596,23 @@ def makewheel(version, output_dir, platform=None):
 
     # Write the panda3d tree.  We use a custom empty __init__ since the
     # default one adds the bin directory to the PATH, which we don't have.
-    whl.write_file_data('panda3d/__init__.py', """"Python bindings for the Panda3D libraries"
+    p3d_init = """"Python bindings for the Panda3D libraries"
 
 __version__ = '{0}'
-""".format(version))
+""".format(version)
+
+    if '27' in ABI_TAG:
+        p3d_init += """
+if __debug__:
+    import sys
+    if sys.version_info < (3, 0):
+        sys.stderr.write("WARNING: Python 2.7 will reach EOL after December 31, 2019.\\n")
+        sys.stderr.write("To suppress this warning, upgrade to Python 3.\\n")
+        sys.stderr.flush()
+    del sys
+"""
+
+    whl.write_file_data('panda3d/__init__.py', p3d_init)
 
     # Copy the extension modules from the panda3d directory.
     ext_suffix = GetExtensionSuffix()

+ 16 - 13
makepanda/test_wheel.py

@@ -17,31 +17,34 @@ from optparse import OptionParser
 def test_wheel(wheel, verbose=False):
     envdir = tempfile.mkdtemp(prefix="venv-")
     print("Setting up virtual environment in {0}".format(envdir))
+    sys.stdout.flush()
 
+    # Make sure pip is up-to-date first.
+    subprocess.call([sys.executable, "-B", "-m", "pip", "install", "-U", "pip"])
+
+    # Create a virtualenv.
     if sys.version_info >= (3, 0):
-        subprocess.call([sys.executable, "-m", "venv", "--clear", envdir])
+        subprocess.call([sys.executable, "-B", "-m", "venv", "--clear", envdir])
     else:
-        subprocess.call([sys.executable, "-m", "virtualenv", "--clear", envdir])
+        subprocess.call([sys.executable, "-B", "-m", "virtualenv", "--clear", envdir])
 
-    # Make sure pip is up-to-date first.
-    if subprocess.call([sys.executable, "-m", "pip", "install", "-U", "pip"]) != 0:
+    # Determine the path to the Python interpreter.
+    if sys.platform == "win32":
+        python = os.path.join(envdir, "Scripts", "python.exe")
+    else:
+        python = os.path.join(envdir, "bin", "python")
+
+    # Upgrade pip inside the environment too.
+    if subprocess.call([python, "-m", "pip", "install", "-U", "pip"]) != 0:
         shutil.rmtree(envdir)
         sys.exit(1)
 
     # Install pytest into the environment, as well as our wheel.
-    if sys.platform == "win32":
-        pip = os.path.join(envdir, "Scripts", "pip.exe")
-    else:
-        pip = os.path.join(envdir, "bin", "pip")
-    if subprocess.call([pip, "install", "pytest", wheel]) != 0:
+    if subprocess.call([python, "-m", "pip", "install", "pytest", wheel]) != 0:
         shutil.rmtree(envdir)
         sys.exit(1)
 
     # Run the test suite.
-    if sys.platform == "win32":
-        python = os.path.join(envdir, "Scripts", "python.exe")
-    else:
-        python = os.path.join(envdir, "bin", "python")
     test_cmd = [python, "-m", "pytest", "tests"]
     if verbose:
         test_cmd.append("--verbose")

+ 3 - 3
panda/src/audio/audio.h

@@ -11,12 +11,12 @@
  * @date 2000-07-06
  */
 
-#ifndef __AUDIO_H__
-#define __AUDIO_H__
+#ifndef AUDIO_H
+#define AUDIO_H
 
 #include "filterProperties.h"
 #include "audioLoadRequest.h"
 #include "audioSound.h"
 #include "audioManager.h"
 
-#endif /* __AUDIO_H__ */
+#endif /* AUDIO_H */

+ 0 - 8
panda/src/audio/audioManager.cxx

@@ -325,11 +325,3 @@ void AudioManager::
 write(std::ostream &out) const {
   out << (*this) << "\n";
 }
-
-/**
- * For use only with Miles.
- */
-void AudioManager::
-set_speaker_configuration(LVecBase3 *speaker1, LVecBase3 *speaker2, LVecBase3 *speaker3, LVecBase3 *speaker4, LVecBase3 *speaker5, LVecBase3 *speaker6, LVecBase3 *speaker7, LVecBase3 *speaker8, LVecBase3 *speaker9) {
-  // intentionally blank
-}

+ 3 - 6
panda/src/audio/audioManager.h

@@ -12,8 +12,8 @@
  * Prior system by: cary
  */
 
-#ifndef __AUDIO_MANAGER_H__
-#define __AUDIO_MANAGER_H__
+#ifndef AUDIOMANAGER_H
+#define AUDIOMANAGER_H
 
 #include "config_audio.h"
 #include "audioSound.h"
@@ -178,9 +178,6 @@ PUBLISHED:
   virtual void output(std::ostream &out) const;
   virtual void write(std::ostream &out) const;
 
-  // set_speaker_configuration is a Miles only method.
-  virtual void set_speaker_configuration(LVecBase3 *speaker1, LVecBase3 *speaker2=nullptr, LVecBase3 *speaker3=nullptr, LVecBase3 *speaker4=nullptr, LVecBase3 *speaker5=nullptr, LVecBase3 *speaker6=nullptr, LVecBase3 *speaker7=nullptr, LVecBase3 *speaker8=nullptr, LVecBase3 *speaker9=nullptr);
-
 public:
   static void register_AudioManager_creator(Create_AudioManager_proc* proc);
 
@@ -222,4 +219,4 @@ operator << (std::ostream &out, const AudioManager &mgr) {
 
 #include "audioManager.I"
 
-#endif /* __AUDIO_MANAGER_H__ */
+#endif /* AUDIOMANAGER_H */

+ 0 - 17
panda/src/audio/audioSound.cxx

@@ -83,23 +83,6 @@ set_speaker_mix(PN_stdfloat frontleft, PN_stdfloat frontright, PN_stdfloat cente
     // intentionally blank
 }
 
-/**
- * For use only with Miles.
- */
-PN_stdfloat AudioSound::
-get_speaker_level(int index) {
-  // intentionally blank
-  return 0.0;
-}
-
-/**
- * For use only with Miles.
- */
-void AudioSound::
-set_speaker_levels(PN_stdfloat level1, PN_stdfloat level2, PN_stdfloat level3, PN_stdfloat level4, PN_stdfloat level5, PN_stdfloat level6, PN_stdfloat level7, PN_stdfloat level8, PN_stdfloat level9) {
-  // intentionally blank
-}
-
 /**
  * Configure the local DSP filter chain.
  *

+ 4 - 11
panda/src/audio/audioSound.h

@@ -12,8 +12,8 @@
  * Prior system by: cary
  */
 
-#ifndef __AUDIOSOUND_H__
-#define __AUDIOSOUND_H__
+#ifndef AUDIOSOUND_H
+#define AUDIOSOUND_H
 
 #include "config_audio.h"
 #include "typedReferenceCount.h"
@@ -104,17 +104,10 @@ PUBLISHED:
   virtual void set_3d_max_distance(PN_stdfloat dist);
   virtual PN_stdfloat get_3d_max_distance() const;
 
-  // *_speaker_mix and *_speaker_level(s) serve the same purpose.
-  // *_speaker_mix is for use with FMOD. *_speaker_level(s) is for use with
-  // Miles.  Both interfaces exist because of a significant difference in the
-  // two APIs.  Hopefully the difference can be reconciled into a single
-  // interface at some point.
+  // *_speaker_mix is for use with FMOD.
   virtual PN_stdfloat get_speaker_mix(int speaker);
   virtual void set_speaker_mix(PN_stdfloat frontleft, PN_stdfloat frontright, PN_stdfloat center, PN_stdfloat sub, PN_stdfloat backleft, PN_stdfloat backright, PN_stdfloat sideleft, PN_stdfloat  sideright);
 
-  virtual PN_stdfloat get_speaker_level(int index);
-  virtual void set_speaker_levels(PN_stdfloat level1, PN_stdfloat level2=-1.0f, PN_stdfloat level3=-1.0f, PN_stdfloat level4=-1.0f, PN_stdfloat level5=-1.0f, PN_stdfloat level6=-1.0f, PN_stdfloat level7=-1.0f, PN_stdfloat level8=-1.0f, PN_stdfloat level9=-1.0f);
-
   virtual int get_priority();
   virtual void set_priority(int priority);
 
@@ -160,4 +153,4 @@ operator << (std::ostream &out, const AudioSound &sound) {
 EXPCL_PANDA_AUDIO std::ostream &
 operator << (std::ostream &out, AudioSound::SoundStatus status);
 
-#endif /* __AUDIOSOUND_H__ */
+#endif /* AUDIOSOUND_H */

+ 0 - 23
panda/src/audio/config_audio.cxx

@@ -100,11 +100,6 @@ ConfigVariableEnum<FmodSpeakerMode> fmod_speaker_mode
           "Options: raw, mono, stereo, quad, surround, 5.1 and 7.1. "));
 
 
-// Config variables for Miles:
-
-ConfigVariableBool audio_software_midi
-("audio-software-midi", true);
-
 ConfigVariableFilename audio_dls_file
 ("audio-dls-file", Filename(),
  PRC_DESC("Specifies a DLS file that defines an instrument set to load "
@@ -113,24 +108,6 @@ ConfigVariableFilename audio_dls_file
           "one is available; the likely success of this depends on the "
           "operating system."));
 
-ConfigVariableBool audio_play_midi
-("audio-play-midi", true);
-
-ConfigVariableBool audio_play_wave
-("audio-play-wave", true);
-
-ConfigVariableBool audio_play_mp3
-("audio-play-mp3", true);
-
-ConfigVariableInt audio_output_rate
-("audio-output-rate", 22050);
-
-ConfigVariableInt audio_output_bits
-("audio-output-bits", 16);
-
-ConfigVariableInt audio_output_channels
-("audio-output-channels", 2);
-
 ConfigureFn(config_audio) {
   FilterProperties::init_type();
   AudioLoadRequest::init_type();

+ 1 - 13
panda/src/audio/config_audio.h

@@ -58,6 +58,7 @@ EXPCL_PANDA_AUDIO std::istream &operator >> (std::istream &in, FmodSpeakerMode &
 extern EXPCL_PANDA_AUDIO ConfigVariableInt fmod_number_of_sound_channels;
 extern EXPCL_PANDA_AUDIO ConfigVariableBool fmod_use_surround_sound;
 extern EXPCL_PANDA_AUDIO ConfigVariableEnum<FmodSpeakerMode> fmod_speaker_mode;
+extern EXPCL_PANDA_AUDIO ConfigVariableFilename audio_dls_file;
 
 // Config vars for OpenAL:
 
@@ -67,19 +68,6 @@ extern EXPCL_PANDA_AUDIO ConfigVariableDouble audio_drop_off_factor;
 extern EXPCL_PANDA_AUDIO ConfigVariableDouble audio_buffering_seconds;
 extern EXPCL_PANDA_AUDIO ConfigVariableInt    audio_preload_threshold;
 
-// Config vars for Miles:
-
-extern EXPCL_PANDA_AUDIO ConfigVariableBool audio_software_midi;
-extern EXPCL_PANDA_AUDIO ConfigVariableFilename audio_dls_file;
-extern EXPCL_PANDA_AUDIO ConfigVariableBool audio_play_midi;
-extern EXPCL_PANDA_AUDIO ConfigVariableBool audio_play_wave;
-extern EXPCL_PANDA_AUDIO ConfigVariableBool audio_play_mp3;
-extern EXPCL_PANDA_AUDIO ConfigVariableInt audio_output_rate;
-extern EXPCL_PANDA_AUDIO ConfigVariableInt audio_output_bits;
-extern EXPCL_PANDA_AUDIO ConfigVariableInt audio_output_channels;
-
-
-
 #ifdef NOTIFY_DEBUG //[
   // Non-release build:
   #define audio_debug(msg) \

+ 4 - 4
panda/src/audio/nullAudioManager.h

@@ -12,8 +12,8 @@
  * Prior system by: cary
  */
 
-#ifndef __NULL_AUDIO_MANAGER_H__
-#define __NULL_AUDIO_MANAGER_H__
+#ifndef NULLAUDIOMANAGER_H
+#define NULLAUDIOMANAGER_H
 
 #include "audioManager.h"
 #include "nullAudioSound.h"
@@ -21,7 +21,7 @@
 class EXPCL_PANDA_AUDIO NullAudioManager : public AudioManager {
   // All of these methods are stubbed out to some degree.  If you're looking
   // for a starting place for a new AudioManager, please consider looking at
-  // the milesAudioManager.
+  // the openalAudioManager.
 
 public:
   NullAudioManager();
@@ -89,4 +89,4 @@ private:
   static TypeHandle _type_handle;
 };
 
-#endif /* __NULL_AUDIO_MANAGER_H__ */
+#endif /* NULLAUDIOMANAGER_H */

+ 4 - 4
panda/src/audio/nullAudioSound.h

@@ -12,8 +12,8 @@
  * Prior system by: cary
  */
 
-#ifndef __NULL_AUDIO_SOUND_H__
-#define __NULL_AUDIO_SOUND_H__
+#ifndef NULLAUDIOSOUND_H
+#define NULLAUDIOSOUND_H
 
 #include "audioSound.h"
 
@@ -23,7 +23,7 @@
 class EXPCL_PANDA_AUDIO NullAudioSound : public AudioSound {
   // All of these methods are stubbed out to some degree.  If you're looking
   // for a starting place for a new AudioManager, please consider looking at
-  // the milesAudioManager.
+  // the openalAudioManager.
 
 public:
   ~NullAudioSound();
@@ -91,4 +91,4 @@ private:
   friend class NullAudioManager;
 };
 
-#endif /* __NULL_AUDIO_SOUND_H__ */
+#endif /* NULLAUDIOSOUND_H */

+ 0 - 102
panda/src/audiotraits/config_milesAudio.cxx

@@ -1,102 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file config_milesAudio.cxx
- * @author skyler
- */
-
-#include "pandabase.h"
-#ifdef HAVE_RAD_MSS //[
-
-#include "config_milesAudio.h"
-#include "milesAudioManager.h"
-#include "milesAudioSound.h"
-#include "milesAudioSample.h"
-#include "milesAudioSequence.h"
-#include "milesAudioStream.h"
-#include "pandaSystem.h"
-#include "dconfig.h"
-
-#if !defined(CPPPARSER) && !defined(LINK_ALL_STATIC) && !defined(BUILDING_MILES_AUDIO)
-  #error Buildsystem error: BUILDING_MILES_AUDIO not defined
-#endif
-
-ConfigureDef(config_milesAudio);
-NotifyCategoryDef(milesAudio, ":audio");
-
-ConfigureFn(config_milesAudio) {
-  init_libMilesAudio();
-}
-
-ConfigVariableBool miles_audio_force_midi_reset
-("audio-force-midi-reset", true);
-
-ConfigVariableInt miles_audio_expand_mp3_threshold
-("miles-audio-expand-mp3-threshold", 16384,
- PRC_DESC("This enables a Miles workaround in which small MP3 files are "
-          "expanded in-memory at load time into WAV format, which can "
-          "work around problems with Miles being unable to correctly "
-          "report the length of, or seek within, a variable bit-rate encoded "
-          "MP3 file.  Any MP3 file whose length in bytes is less than "
-          "this value will be expanded.  This only applies to files "
-          "within the miles-audio-preload-threshold."));
-
-ConfigVariableInt miles_audio_preload_threshold
-("miles-audio-preload-threshold", -1,
- PRC_DESC("This should be no smaller "
-          "than miles-audio-expand-mp3-threshold.  Files that are smaller "
-          "than this number of bytes will be preloaded and kept "
-          "resident in memory, while files that are this size or larger "
-          "will be streamed from disk.  Set this to -1 to preload "
-          "every file."));
-
-ConfigVariableBool miles_audio_panda_threads
-("miles-audio-panda-threads", true,
- PRC_DESC("Set this true to service Miles background audio via Panda's "
-          "threading interface, instead of Miles' built-in threading "
-          "interface.  This gives Panda more control over the threading, "
-          "and ensures better lock protection within Panda.  This has "
-          "no meaning unless Panda is compiled with thread support."));
-
-/**
- * Initializes the library.  This must be called at least once before any of
- * the functions or classes in this library can be used.  Normally it will be
- * called by the static initializers and need not be called explicitly, but
- * special cases exist.
- */
-void
-init_libMilesAudio() {
-  static bool initialized = false;
-  if (initialized) {
-    return;
-  }
-  initialized = true;
-  MilesAudioManager::init_type();
-  MilesAudioSound::init_type();
-  MilesAudioSample::init_type();
-  MilesAudioSequence::init_type();
-  MilesAudioStream::init_type();
-
-  PandaSystem *ps = PandaSystem::get_global_ptr();
-  ps->add_system("Miles");
-  ps->add_system("audio");
-  ps->set_system_tag("audio", "implementation", "Miles");
-}
-
-/**
- * This function is called when the dynamic library is loaded; it should
- * return the Create_AudioManager function appropriate to create a
- * MilesAudioManager.
- */
-Create_AudioManager_proc *
-get_audio_manager_func_miles_audio() {
-  init_libMilesAudio();
-  return &Create_MilesAudioManager;
-}
-
-#endif //]

+ 0 - 37
panda/src/audiotraits/config_milesAudio.h

@@ -1,37 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file config_milesAudio.h
- * @author skyler
- */
-
-#ifndef CONFIG_MILESAUDIO_H
-#define CONFIG_MILESAUDIO_H
-
-#include "pandabase.h"
-
-#ifdef HAVE_RAD_MSS //[
-#include "notifyCategoryProxy.h"
-#include "configVariableBool.h"
-#include "configVariableInt.h"
-#include "dconfig.h"
-#include "audioManager.h"
-
-ConfigureDecl(config_milesAudio, EXPCL_MILES_AUDIO, EXPTP_MILES_AUDIO);
-NotifyCategoryDecl(milesAudio, EXPCL_MILES_AUDIO, EXPTP_MILES_AUDIO);
-
-extern ConfigVariableBool miles_audio_force_midi_reset;
-extern ConfigVariableInt miles_audio_expand_mp3_threshold;
-extern ConfigVariableInt miles_audio_preload_threshold;
-extern ConfigVariableBool miles_audio_panda_threads;
-
-extern EXPCL_MILES_AUDIO void init_libMilesAudio();
-extern "C" EXPCL_MILES_AUDIO Create_AudioManager_proc *get_audio_manager_func_miles_audio();
-#endif //]
-
-#endif // CONFIG_MILESAUDIO_H

+ 0 - 39
panda/src/audiotraits/globalMilesManager.I

@@ -1,39 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file globalMilesManager.I
- * @author drose
- * @date 2007-07-30
- */
-
-/**
- * Returns true if the Miles Sound System is open (and active), false if it is
- * not.
- */
-INLINE bool GlobalMilesManager::
-is_open() const {
-  return _is_open;
-}
-
-/**
- * Returns the number of sample handles that have been allocated.
- */
-INLINE int GlobalMilesManager::
-get_num_samples() const {
-  LightMutexHolder holder(_samples_lock);
-  return _samples.size();
-}
-
-/**
- * Returns the number of sequence handles that have been allocated.
- */
-INLINE int GlobalMilesManager::
-get_num_sequences() const {
-  LightMutexHolder holder(_sequences_lock);
-  return _sequences.size();
-}

+ 0 - 446
panda/src/audiotraits/globalMilesManager.cxx

@@ -1,446 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file globalMilesManager.cxx
- * @author drose
- * @date 2007-07-26
- */
-
-#include "globalMilesManager.h"
-
-#ifdef HAVE_RAD_MSS //[
-
-#include "lightMutexHolder.h"
-#include "milesAudioManager.h"
-#include "milesAudioSample.h"
-#include "milesAudioSequence.h"
-
-#ifdef WIN32
-// For midiOutReset()
-#include <windows.h>
-#include <mmsystem.h>
-#endif
-
-using std::istream;
-using std::string;
-
-GlobalMilesManager *GlobalMilesManager::_global_ptr;
-
-/**
- *
- */
-GlobalMilesManager::
-GlobalMilesManager() :
-  _managers_lock("GlobalMilesManager::_managers_lock"),
-  _samples_lock("GlobalMilesManager::_samples_lock"),
-  _sequences_lock("GlobalMilesManager::_sequences_lock")
-{
-  _digital_driver = 0;
-  _midi_driver = 0;
-  _dls_device = 0;
-  _dls_file = 0;
-  _is_open = false;
-}
-
-/**
- * Records a new MilesAudioManager in the world.  This will open the Miles API
- * when the first audio manager is added.
- */
-void GlobalMilesManager::
-add_manager(MilesAudioManager *manager) {
-  LightMutexHolder holder(_managers_lock);
-  _managers.insert(manager);
-  if (!_is_open) {
-    open_api();
-  }
-}
-
-/**
- * Records that a MilesAudioManager is destructing.  This will clsoe the Miles
- * API when the last audio manager is removed.
- */
-void GlobalMilesManager::
-remove_manager(MilesAudioManager *manager) {
-  LightMutexHolder holder(_managers_lock);
-  _managers.erase(manager);
-  if (_managers.empty() && _is_open) {
-    close_api();
-  }
-}
-
-/**
- * Calls cleanup() on all MilesAudioManagers, to cause a clean shutdown.
- */
-void GlobalMilesManager::
-cleanup() {
-  LightMutexHolder holder(_managers_lock);
-  Managers::iterator mi;
-  for (mi = _managers.begin(); mi != _managers.end(); ++mi) {
-    (*mi)->cleanup();
-  }
-}
-
-/**
- * Gets a sample handle from the global pool for the digital output device, to
- * be used with the indicated AudioSound.
- *
- * If successful, sets the sample handle and the index (which should later be
- * used to release the sample) and returns true.  If unsuccessful (because
- * there are no more available handles), returns false.
- *
- * This is a very limited resource; you should only get a sample just before
- * playing a sound.
- */
-bool GlobalMilesManager::
-get_sample(HSAMPLE &sample, size_t &index, MilesAudioSample *sound) {
-  LightMutexHolder holder(_samples_lock);
-
-  for (size_t i = 0; i < _samples.size(); ++i) {
-    SampleData &smp = _samples[i];
-    if (AIL_sample_status(smp._sample) == SMP_DONE) {
-      if (smp._sound != nullptr) {
-        // Tell the last sound that was using this sample that it's done now.
-        smp._sound->internal_stop();
-      }
-      smp._sound = sound;
-      sample = smp._sample;
-      index = i;
-      return true;
-    }
-  }
-
-  // No more already-allocated samples; get a new one from the system.
-  sample = AIL_allocate_sample_handle(_digital_driver);
-  if (sample == 0) {
-    return false;
-  }
-
-  AIL_init_sample(sample, DIG_F_STEREO_16, 0);
-  index = _samples.size();
-
-  SampleData smp;
-  smp._sound = sound;
-  smp._sample = sample;
-  _samples.push_back(smp);
-  return true;
-}
-
-/**
- * Indicates that the indicated AudioSound no longer needs this sample.
- */
-void GlobalMilesManager::
-release_sample(size_t index, MilesAudioSample *sound) {
-  LightMutexHolder holder(_samples_lock);
-  nassertv(index < _samples.size());
-
-  SampleData &smp = _samples[index];
-  if (smp._sound == sound) {
-    smp._sound = nullptr;
-  }
-}
-
-/**
- * Gets a sequence handle from the global pool for the digital output device,
- * to be used with the indicated AudioSound.
- *
- * If successful, sets the sequence handle and the index (which should later
- * be used to release the sequence) and returns true.  If unsuccessful
- * (because there are no more available handles), returns false.
- *
- * This is a very limited resource; you should only get a sequence just before
- * playing a sound.
- */
-bool GlobalMilesManager::
-get_sequence(HSEQUENCE &sequence, size_t &index, MilesAudioSequence *sound) {
-  LightMutexHolder holder(_sequences_lock);
-
-  for (size_t i = 0; i < _sequences.size(); ++i) {
-    SequenceData &seq = _sequences[i];
-    if (AIL_sequence_status(seq._sequence) == SEQ_DONE) {
-      if (seq._sound != nullptr) {
-        // Tell the last sound that was using this sequence that it's done
-        // now.
-        seq._sound->internal_stop();
-      }
-      seq._sound = sound;
-      sequence = seq._sequence;
-      index = i;
-      return true;
-    }
-  }
-
-  // No more already-allocated sequences; get a new one from the system.
-  sequence = AIL_allocate_sequence_handle(_midi_driver);
-  if (sequence == 0) {
-    return false;
-  }
-
-  index = _sequences.size();
-
-  SequenceData seq;
-  seq._sound = sound;
-  seq._sequence = sequence;
-  _sequences.push_back(seq);
-  return true;
-}
-
-/**
- * Indicates that the indicated AudioSound no longer needs this sequence.
- */
-void GlobalMilesManager::
-release_sequence(size_t index, MilesAudioSequence *sound) {
-  LightMutexHolder holder(_sequences_lock);
-  nassertv(index < _sequences.size());
-
-  SequenceData &seq = _sequences[index];
-  if (seq._sound == sound) {
-    seq._sound = nullptr;
-  }
-}
-
-/**
- * Sometimes Miles seems to leave midi notes hanging, even after stop is
- * called, so call this method to perform an explicit reset using winMM.dll
- * calls, just to ensure silence.
- */
-void GlobalMilesManager::
-force_midi_reset() {
-  if (!miles_audio_force_midi_reset) {
-    audio_debug("MilesAudioManager::skipping force_midi_reset");
-    return;
-  }
-  audio_debug("MilesAudioManager::force_midi_reset");
-
-#ifdef WIN32
-  if ((_midi_driver!=nullptr) && (_midi_driver->deviceid != MIDI_nullptr_DRIVER) && (_midi_driver->hMidiOut != nullptr)) {
-    audio_debug("MilesAudioManager::calling midiOutReset");
-    midiOutReset(_midi_driver->hMidiOut);
-  }
-#endif
-}
-
-/**
- * Returns the pointer to the one GlobalMilesManager object.
- */
-GlobalMilesManager *GlobalMilesManager::
-get_global_ptr() {
-  if (_global_ptr == nullptr) {
-    _global_ptr = new GlobalMilesManager;
-  }
-  return _global_ptr;
-}
-
-/**
- * Called internally to initialize the Miles API.
- */
-void GlobalMilesManager::
-open_api() {
-  audio_debug("GlobalMilesManager::open_api()")
-  nassertv(!_is_open);
-
-  bool use_digital = (audio_play_wave || audio_play_mp3);
-  if (audio_play_midi && audio_software_midi) {
-    use_digital = true;
-  }
-
-#ifdef IS_OSX
-  audio_software_midi = true;
-#endif
-
-  audio_debug("  use_digital="<<use_digital);
-  audio_debug("  audio_play_midi="<<audio_play_midi);
-  audio_debug("  audio_software_midi="<<audio_software_midi);
-  audio_debug("  audio_output_rate="<<audio_output_rate);
-  audio_debug("  audio_output_bits="<<audio_output_bits);
-  audio_debug("  audio_output_channels="<<audio_output_channels);
-  audio_debug("  audio_software_midi="<<audio_software_midi);
-
-#if !defined(NDEBUG) && defined(AIL_MSS_version) //[
-  char version[8];
-  AIL_MSS_version(version, 8);
-  audio_debug("  Mss32.dll Version: "<<version);
-#endif //]
-
-  if (!AIL_startup()) {
-    milesAudio_cat.warning()
-      << "Miles Sound System already initialized!\n";
-  }
-
-  AIL_set_file_callbacks(open_callback, close_callback,
-                         seek_callback, read_callback);
-
-  if (use_digital) {
-    _digital_driver =
-      AIL_open_digital_driver(audio_output_rate, audio_output_bits,
-                              audio_output_channels, 0);
-  }
-
-  if (audio_play_midi) {
-    if (audio_software_midi) {
-      _midi_driver = AIL_open_XMIDI_driver(AIL_OPEN_XMIDI_NULL_DRIVER);
-
-      // Load the downloadable sounds file:
-      _dls_device = AIL_DLS_open(_midi_driver, _digital_driver, nullptr, 0,
-                                 audio_output_rate, audio_output_bits,
-                                 audio_output_channels);
-
-      Filename dls_pathname = AudioManager::get_dls_pathname();
-
-      VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
-      vfs->resolve_filename(dls_pathname, get_model_path());
-
-      _dls_data.clear();
-      PT(VirtualFile) file = vfs->get_file(dls_pathname);
-      if (file == nullptr) {
-        milesAudio_cat.warning()
-          << "DLS file does not exist: " << dls_pathname << "\n";
-
-      } else if (!file->read_file(_dls_data, true)) {
-        milesAudio_cat.warning()
-          << "Could not read DLS file: " << dls_pathname << "\n";
-
-      } else if (_dls_data.empty()) {
-        milesAudio_cat.warning()
-          << "DLS file is empty: " << dls_pathname << "\n";
-
-      } else {
-        _dls_file = AIL_DLS_load_memory(_dls_device, &_dls_data[0], 0);
-      }
-
-      if (_dls_file == 0) {
-        audio_error("  Could not get DLS file, switching to hardware MIDI.");
-        AIL_DLS_close(_dls_device, 0);
-        _dls_device = 0;
-        AIL_close_XMIDI_driver(_midi_driver);
-        _midi_driver = AIL_open_XMIDI_driver(0);
-
-      } else {
-        audio_info("  using Miles software midi");
-      }
-    } else {
-      _midi_driver = AIL_open_XMIDI_driver(0);
-      audio_info("  using Miles hardware midi");
-    }
-  }
-
-  _is_open = true;
-}
-
-/**
- * Called internally to shut down the Miles API.
- */
-void GlobalMilesManager::
-close_api() {
-  audio_debug("GlobalMilesManager::close_api()")
-  nassertv(_is_open);
-
-  Samples::iterator si;
-  for (si = _samples.begin(); si != _samples.end(); ++si) {
-    SampleData &smp = (*si);
-    AIL_release_sample_handle(smp._sample);
-  }
-  _samples.clear();
-
-  Sequences::iterator qi;
-  for (qi = _sequences.begin(); qi != _sequences.end(); ++qi) {
-    SequenceData &smp = (*qi);
-    AIL_release_sequence_handle(smp._sequence);
-  }
-  _sequences.clear();
-
-  if (_dls_file != 0) {
-    AIL_DLS_unload(_dls_device, _dls_file);
-    _dls_file = 0;
-  }
-
-  if (_dls_device != 0) {
-    AIL_DLS_close(_dls_device, 0);
-    _dls_device = 0;
-  }
-
-  if (_midi_driver != 0) {
-    AIL_close_XMIDI_driver(_midi_driver);
-    _midi_driver = 0;
-  }
-
-  if (_digital_driver != 0) {
-    AIL_close_digital_driver(_digital_driver);
-    _digital_driver = 0;
-  }
-
-  AIL_shutdown();
-
-  _is_open = false;
-}
-
-/**
- * This callback function is given to Miles to handle file I/O via the Panda
- * VFS.  It's only used to implemented streaming audio files, since in all
- * other cases we open files directly.
- */
-U32 AILCALLBACK GlobalMilesManager::
-open_callback(char const *filename, UINTa *file_handle) {
-  VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
-  istream *strm = vfs->open_read_file(Filename::binary_filename(string(filename)), true);
-  if (strm == nullptr) {
-    // Failure.
-    return 0;
-  }
-  // Success.
-  (*file_handle) = (UINTa)strm;
-  return 1;
-}
-
-/**
- * This callback function is given to Miles to handle file I/O via the Panda
- * VFS.
- */
-void AILCALLBACK GlobalMilesManager::
-close_callback(UINTa file_handle) {
-  istream *strm = (istream *)file_handle;
-  VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
-  vfs->close_read_file(strm);
-}
-
-/**
- * This callback function is given to Miles to handle file I/O via the Panda
- * VFS.
- */
-S32 AILCALLBACK GlobalMilesManager::
-seek_callback(UINTa file_handle, S32 offset, U32 type) {
-  istream *strm = (istream *)file_handle;
-  strm->clear();
-  switch (type) {
-  case AIL_FILE_SEEK_BEGIN:
-    strm->seekg(offset, std::ios::beg);
-    break;
-
-  case AIL_FILE_SEEK_CURRENT:
-    strm->seekg(offset, std::ios::cur);
-    break;
-
-  case AIL_FILE_SEEK_END:
-    strm->seekg(offset, std::ios::end);
-    break;
-  }
-
-  return strm->tellg();
-}
-
-/**
- * This callback function is given to Miles to handle file I/O via the Panda
- * VFS.
- */
-U32 AILCALLBACK GlobalMilesManager::
-read_callback(UINTa file_handle, void *buffer, U32 bytes) {
-  istream *strm = (istream *)file_handle;
-  strm->read((char *)buffer, bytes);
-  return strm->gcount();
-}
-
-#endif //]

+ 0 - 117
panda/src/audiotraits/globalMilesManager.h

@@ -1,117 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file globalMilesManager.h
- * @author drose
- * @date 2007-07-26
- */
-
-#ifndef GLOBALMILESMANAGER_H
-#define GLOBALMILESMANAGER_H
-
-#include "pandabase.h"
-#ifdef HAVE_RAD_MSS //[
-
-#include "pset.h"
-#include "lightMutex.h"
-#include "lightMutexHolder.h"
-
-#include <mss.h>
-
-#ifndef UINTa
-#define UINTa U32
-#endif
-
-#ifndef SINTa
-#define SINTa S32
-#endif
-
-class MilesAudioSample;
-class MilesAudioSequence;
-
-/**
- * This is a wrapper around the parts of the Miles API that should only be
- * created once.  This represents the global data common to all
- * MilesAudioManagers.
- */
-class EXPCL_MILES_AUDIO GlobalMilesManager {
-private:
-  GlobalMilesManager();
-
-public:
-  void add_manager(MilesAudioManager *manager);
-  void remove_manager(MilesAudioManager *manager);
-  void cleanup();
-  INLINE bool is_open() const;
-
-  bool get_sample(HSAMPLE &sample, size_t &index, MilesAudioSample *sound);
-  void release_sample(size_t index, MilesAudioSample *sound);
-  INLINE int get_num_samples() const;
-
-  bool get_sequence(HSEQUENCE &sequence, size_t &index, MilesAudioSequence *sound);
-  void release_sequence(size_t index, MilesAudioSequence *sound);
-  INLINE int get_num_sequences() const;
-
-  void force_midi_reset();
-
-  static GlobalMilesManager *get_global_ptr();
-
-public:
-  HDIGDRIVER _digital_driver;
-  HMDIDRIVER _midi_driver;
-
-  // For software MIDI:
-  HDLSDEVICE _dls_device;
-  HDLSFILEID _dls_file;
-  vector_uchar _dls_data;
-
-private:
-  void open_api();
-  void close_api();
-
-  static U32 AILCALLBACK open_callback(char const *filename, UINTa *file_handle);
-  static void AILCALLBACK close_callback(UINTa file_handle);
-  static S32 AILCALLBACK seek_callback(UINTa file_handle, S32 offset, U32 type);
-  static U32 AILCALLBACK read_callback(UINTa file_handle, void *buffer, U32 bytes);
-
-
-private:
-  bool _is_open;
-
-  typedef pset<MilesAudioManager *> Managers;
-  Managers _managers;
-  LightMutex _managers_lock;
-
-  class SampleData {
-  public:
-    HSAMPLE _sample;
-    MilesAudioSample *_sound;
-  };
-
-  typedef pvector<SampleData> Samples;
-  Samples _samples;
-  LightMutex _samples_lock;
-
-  class SequenceData {
-  public:
-    HSEQUENCE _sequence;
-    MilesAudioSequence *_sound;
-  };
-
-  typedef pvector<SequenceData> Sequences;
-  Sequences _sequences;
-  LightMutex _sequences_lock;
-
-  static GlobalMilesManager *_global_ptr;
-};
-
-#include "globalMilesManager.I"
-
-#endif //]
-
-#endif

+ 0 - 1121
panda/src/audiotraits/milesAudioManager.cxx

@@ -1,1121 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file milesAudioManager.cxx
- * @author skyler
- * @date 2001-06-06
- * Prior system by: cary
- */
-
-#include "milesAudioManager.h"
-
-#ifdef HAVE_RAD_MSS //[
-
-#include "milesAudioSound.h"
-#include "milesAudioSample.h"
-#include "milesAudioStream.h"
-#include "globalMilesManager.h"
-#include "config_audio.h"
-#include "config_putil.h"
-#include "config_express.h"
-#include "virtualFileSystem.h"
-#include "nullAudioSound.h"
-#include "string_utils.h"
-#include "mutexHolder.h"
-#include "lightReMutexHolder.h"
-
-#include <algorithm>
-
-using std::string;
-
-
-TypeHandle MilesAudioManager::_type_handle;
-
-AudioManager *Create_MilesAudioManager() {
-  audio_debug("Create_MilesAudioManager()");
-  return new MilesAudioManager();
-}
-
-/**
- * Create an audio manager.  This may open the Miles sound system if there
- * were no other MilesAudioManager instances.  Subsequent managers may use the
- * same Miles resources.
- */
-MilesAudioManager::
-MilesAudioManager() :
-  _lock("MilesAudioManager::_lock"),
-  _streams_lock("MilesAudioManager::_streams_lock"),
-  _streams_cvar(_streams_lock)
-{
-  audio_debug("MilesAudioManager::MilesAudioManager(), this = "
-              << (void *)this);
-  GlobalMilesManager::get_global_ptr()->add_manager(this);
-  audio_debug("  audio_active="<<audio_active);
-  audio_debug("  audio_volume="<<audio_volume);
-  _cleanup_required = true;
-  _active = audio_active;
-  _volume = audio_volume;
-  _play_rate = 1.0f;
-  _cache_limit = audio_cache_limit;
-  _concurrent_sound_limit = 0;
-  _is_valid = true;
-  _hasMidiSounds = false;
-  _sounds_finished = false;
-
-  // We used to hang a call to a force-shutdown function on atexit(), so that
-  // any running sounds (particularly MIDI sounds) would be silenced on exit,
-  // especially a sudden exit triggered by a Python exception.  But that
-  // causes problems because Miles itself also hangs a force-shutdown function
-  // on atexit(), and you can't call AIL_cleanup() twice--that results in a
-  // crash.
-
-  // Nowadays, we provide the AudioManager::shutdown() method instead, which
-  // allows the app to force all sounds to stop cleanly before we get to the
-  // atexit() stack.  In Python, we guarantee that this method will be called
-  // in the sys.exitfunc chain.
-}
-
-/**
- * Clean up this audio manager and possibly release the Miles resources that
- * are reserved by the application (the later happens if this is the last
- * active manager).
- */
-MilesAudioManager::
-~MilesAudioManager() {
-  audio_debug("MilesAudioManager::~MilesAudioManager(), this = "
-              << (void *)this);
-  cleanup();
-  GlobalMilesManager::get_global_ptr()->remove_manager(this);
-
-  audio_debug("MilesAudioManager::~MilesAudioManager() finished");
-}
-
-/**
- * Call this at exit time to shut down the audio system.  This will invalidate
- * all currently-active AudioManagers and AudioSounds in the system.  If you
- * change your mind and want to play sounds again, you will have to recreate
- * all of these objects.
- */
-void MilesAudioManager::
-shutdown() {
-  audio_debug("shutdown() started");
-  GlobalMilesManager::get_global_ptr()->cleanup();
-  audio_debug("shutdown() finished");
-}
-
-/**
- * This is mostly for debugging, but it it could be used to detect errors in a
- * release build if you don't mind the cpu cost.
- */
-bool MilesAudioManager::
-is_valid() {
-  LightReMutexHolder holder(_lock);
-  return do_is_valid();
-}
-
-/**
- *
- */
-PT(AudioSound) MilesAudioManager::
-get_sound(const Filename &file_name, bool, int) {
-  LightReMutexHolder holder(_lock);
-  audio_debug("MilesAudioManager::get_sound(file_name=\""<<file_name<<"\")");
-
-  if (!do_is_valid()) {
-     audio_debug("invalid MilesAudioManager returning NullSound");
-     return get_null_sound();
-  }
-
-  Filename path = file_name;
-
-  VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
-  vfs->resolve_filename(path, get_model_path());
-  audio_debug("Reading "<<path);
-  audio_debug("  resolved file_name is '"<<path<<"'");
-
-  PT(SoundData) sd;
-  // Get the sound, either from the cache or from a loader:
-  SoundMap::const_iterator si=_sounds.find(path);
-  if (si != _sounds.end()) {
-    // ...found the sound in the cache.
-    sd = (*si).second;
-    audio_debug("  sound found in pool 0x" << (void*)sd);
-
-  } else {
-    // ...the sound was not found in the cachepool.
-    sd = load(path);
-    if (sd != nullptr) {
-      while (_sounds.size() >= (unsigned int)_cache_limit) {
-        uncache_a_sound();
-      }
-      // Put it in the pool: The following is roughly like: _sounds[path] =
-      // sd; But, it gives us an iterator into the map.
-      std::pair<SoundMap::const_iterator, bool> ib
-          = _sounds.insert(SoundMap::value_type(path, sd));
-      if (!ib.second) {
-        // The insert failed.
-        audio_debug("  failed map insert of "<<path);
-        nassertr(do_is_valid(), nullptr);
-        return get_null_sound();
-      }
-      // Set si, so that we can get a reference to the path for the
-      // MilesAudioSound.
-      si=ib.first;
-    }
-  }
-  // Create an AudioSound from the sound:
-  PT(AudioSound) audioSound;
-
-  if (sd != nullptr) {
-    most_recently_used((*si).first);
-    if (sd->_file_type == AILFILETYPE_MIDI ||
-        sd->_file_type == AILFILETYPE_XMIDI ||
-        sd->_file_type == AILFILETYPE_XMIDI_DLS ||
-        sd->_file_type == AILFILETYPE_XMIDI_MLS) {
-      // MIDI file.
-      audioSound = new MilesAudioSequence(this, sd, file_name);
-
-    } else if (!sd->_raw_data.empty()) {
-      // WAV or MP3 file preloaded into memory.
-      audioSound = new MilesAudioSample(this, sd, file_name);
-
-    } else {
-      // WAV or MP3 file streamed from disk.
-      audioSound = new MilesAudioStream(this, file_name, path);
-    }
-
-    audioSound->set_active(_active);
-
-    bool inserted = _sounds_on_loan.insert((MilesAudioSound *)audioSound.p()).second;
-    nassertr(inserted, audioSound);
-
-    _hasMidiSounds |= (file_name.find(".mid")!=string::npos);
-  } else {
-    // Couldn't load the file; just return a NullAudioSound.
-    audioSound = new NullAudioSound;
-  }
-
-  audio_debug("  returning 0x" << (void*)audioSound);
-  nassertr(do_is_valid(), nullptr);
-  return audioSound;
-}
-
-/**
- *
- */
-PT(AudioSound) MilesAudioManager::
-get_sound(MovieAudio *sound, bool, int) {
-  nassert_raise("Miles audio manager does not support MovieAudio sources.");
-  return nullptr;
-}
-
-/**
- *
- */
-void MilesAudioManager::
-uncache_sound(const Filename &file_name) {
-  audio_debug("MilesAudioManager::uncache_sound(file_name=\""
-      <<file_name<<"\")");
-  LightReMutexHolder holder(_lock);
-  nassertv(do_is_valid());
-  Filename path = file_name;
-
-  VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
-  vfs->resolve_filename(path, get_model_path());
-
-  audio_debug("  path=\""<<path<<"\"");
-  SoundMap::iterator i = _sounds.find(path);
-  if (i != _sounds.end()) {
-    nassertv(_lru.size() > 0);
-    LRU::iterator lru_i = find(_lru.begin(), _lru.end(), &(i->first));
-    nassertv(lru_i != _lru.end());
-    _lru.erase(lru_i);
-    _sounds.erase(i);
-  }
-  nassertv(do_is_valid());
-}
-
-/**
- * Clear out the sound cache.
- */
-void MilesAudioManager::
-clear_cache() {
-  audio_debug("MilesAudioManager::clear_cache()");
-  LightReMutexHolder holder(_lock);
-  do_clear_cache();
-}
-
-/**
- * Set the number of sounds that the cache can hold.
- */
-void MilesAudioManager::
-set_cache_limit(unsigned int count) {
-  LightReMutexHolder holder(_lock);
-
-  audio_debug("MilesAudioManager::set_cache_limit(count="<<count<<")");
-  nassertv(do_is_valid());
-  while (_lru.size() > count) {
-    uncache_a_sound();
-  }
-  _cache_limit=count;
-  nassertv(do_is_valid());
-}
-
-/**
- *
- */
-unsigned int MilesAudioManager::
-get_cache_limit() const {
-  return _cache_limit;
-}
-
-/**
- * set the overall volume
- */
-void MilesAudioManager::
-set_volume(PN_stdfloat volume) {
-  audio_debug("MilesAudioManager::set_volume(volume="<<volume<<")");
-  LightReMutexHolder holder(_lock);
-  if (_volume != volume) {
-    _volume = volume;
-    // Tell our AudioSounds to adjust:
-    AudioSet::iterator i = _sounds_on_loan.begin();
-    for (; i!=_sounds_on_loan.end(); ++i) {
-      (*i)->set_volume((*i)->get_volume());
-    }
-  }
-}
-
-/**
- * get the overall volume
- */
-PN_stdfloat MilesAudioManager::
-get_volume() const {
-  return _volume;
-}
-
-/**
- * set the overall play rate
- */
-void MilesAudioManager::
-set_play_rate(PN_stdfloat play_rate) {
-  audio_debug("MilesAudioManager::set_play_rate(play_rate="<<play_rate<<")");
-  LightReMutexHolder holder(_lock);
-  if (_play_rate != play_rate) {
-    _play_rate = play_rate;
-    // Tell our AudioSounds to adjust:
-    AudioSet::iterator i = _sounds_on_loan.begin();
-    for (; i != _sounds_on_loan.end(); ++i) {
-      (*i)->set_play_rate((*i)->get_play_rate());
-    }
-  }
-}
-
-/**
- * get the overall speed/pitch/play rate
- */
-PN_stdfloat MilesAudioManager::
-get_play_rate() const {
-  return _play_rate;
-}
-
-/**
- * turn on/off
- */
-void MilesAudioManager::
-set_active(bool active) {
-  audio_debug("MilesAudioManager::set_active(flag="<<active<<")");
-  LightReMutexHolder holder(_lock);
-  if (_active != active) {
-    _active=active;
-    // Tell our AudioSounds to adjust:
-    AudioSet::iterator i = _sounds_on_loan.begin();
-    for (; i != _sounds_on_loan.end(); ++i) {
-      (*i)->set_active(_active);
-    }
-
-    if ((!_active) && _hasMidiSounds) {
-      GlobalMilesManager::get_global_ptr()->force_midi_reset();
-    }
-  }
-}
-
-/**
- *
- */
-bool MilesAudioManager::
-get_active() const {
-  return _active;
-}
-
-/**
- *
- */
-void MilesAudioManager::
-set_concurrent_sound_limit(unsigned int limit) {
-  LightReMutexHolder holder(_lock);
-  _concurrent_sound_limit = limit;
-  do_reduce_sounds_playing_to(_concurrent_sound_limit);
-}
-
-/**
- *
- */
-unsigned int MilesAudioManager::
-get_concurrent_sound_limit() const {
-  return _concurrent_sound_limit;
-}
-
-/**
- *
- */
-void MilesAudioManager::
-reduce_sounds_playing_to(unsigned int count) {
-  LightReMutexHolder holder(_lock);
-  do_reduce_sounds_playing_to(count);
-}
-
-/**
- * Stop playback on all sounds managed by this manager.
- */
-void MilesAudioManager::
-stop_all_sounds() {
-  audio_debug("MilesAudioManager::stop_all_sounds()");
-  reduce_sounds_playing_to(0);
-}
-
-/**
- * Set spatial attributes of the listener for 3D sounds.  Note that Y and Z
- * are switched to translate into Miles's coordinate system.
- */
-void MilesAudioManager::audio_3d_set_listener_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, PN_stdfloat vx, PN_stdfloat vy, PN_stdfloat vz, PN_stdfloat fx, PN_stdfloat fy, PN_stdfloat fz, PN_stdfloat ux, PN_stdfloat uy, PN_stdfloat uz) {
-  audio_debug("MilesAudioManager::audio_3d_set_listener_attributes()");
-
-  GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
-  AIL_set_listener_3D_position(mgr->_digital_driver, px, pz, py);
-  AIL_set_listener_3D_velocity_vector(mgr->_digital_driver, vx, vz, vy);
-  AIL_set_listener_3D_orientation(mgr->_digital_driver, fx, fz, fy, ux, uz, uy);
-}
-
-/**
- * Get spatial attributes of the listener for 3D sounds.  Note that Y and Z
- * are switched to translate from Miles's coordinate system.
- */
-void MilesAudioManager::audio_3d_get_listener_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz, PN_stdfloat *fx, PN_stdfloat *fy, PN_stdfloat *fz, PN_stdfloat *ux, PN_stdfloat *uy, PN_stdfloat *uz) {
-  audio_debug("MilesAudioManager::audio_3d_get_listener_attributes()");
-
-  GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
-  float lpx, lpy, lpz, lvx, lvy, lvz, lfx, lfy, lfz, lux, luy, luz;
-  AIL_listener_3D_position(mgr->_digital_driver, &lpx, &lpz, &lpy);
-  AIL_listener_3D_velocity(mgr->_digital_driver, &lvx, &lvz, &lvy);
-  AIL_listener_3D_orientation(mgr->_digital_driver, &lfx, &lfz, &lfy, &lux, &luz, &luy);
-
-  *px = lpx;
-  *py = lpy;
-  *pz = lpz;
-  *vx = lvx;
-  *vy = lvy;
-  *vz = lvz;
-  *fx = lfx;
-  *fy = lfy;
-  *fz = lfz;
-  *ux = lux;
-  *uy = luy;
-  *uz = luz;
-}
-
-/**
- * Set factor to allow user to easily work in a different scale.  1.0
- * represents meters.
- */
-void MilesAudioManager::audio_3d_set_distance_factor(PN_stdfloat factor) {
-  audio_debug("MilesAudioManager::audio_3d_set_distance_factor( factor= " << factor << ")");
-
-  GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
-  AIL_set_3D_distance_factor(mgr->_digital_driver, factor);
-}
-
-/**
- * Get factor controlling working units.
- */
-PN_stdfloat MilesAudioManager::audio_3d_get_distance_factor() const {
-  audio_debug("MilesAudioManager::audio_3d_get_distance_factor()");
-
-  GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
-  return AIL_3D_distance_factor(mgr->_digital_driver);
-}
-
-/**
- * Exaggerates or diminishes the Doppler effect.  Defaults to 1.0
- */
-void MilesAudioManager::audio_3d_set_doppler_factor(PN_stdfloat factor) {
-  audio_debug("MilesAudioManager::audio_3d_set_doppler_factor(factor="<<factor<<")");
-
-  GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
-  AIL_set_3D_doppler_factor(mgr->_digital_driver, factor);
-}
-
-/**
- * Get the factor controlling the Doppler effect.
- */
-PN_stdfloat MilesAudioManager::audio_3d_get_doppler_factor() const {
-  audio_debug("MilesAudioManager::audio_3d_get_doppler_factor()");
-
-  GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
-  return AIL_3D_doppler_factor(mgr->_digital_driver);
-}
-
-/**
- * Control the effect distance has on audability.  Defaults to 1.0
- */
-void MilesAudioManager::audio_3d_set_drop_off_factor(PN_stdfloat factor) {
-  audio_debug("MilesAudioManager::audio_3d_set_drop_off_factor("<<factor<<")");
-
-  GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
-  AIL_set_3D_rolloff_factor(mgr->_digital_driver, factor);
-}
-
-/**
- * Get the factor controlling how quickly sound falls off with distance.
- */
-PN_stdfloat MilesAudioManager::audio_3d_get_drop_off_factor() const {
-  audio_debug("MilesAudioManager::audio_3d_get_drop_off_factor()");
-
-  GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
-  return AIL_3D_rolloff_factor(mgr->_digital_driver);
-}
-
-/**
- * Works similarly to MilesAudioSound::set_speaker_levels, but specifies the
- * 3D positions of the speakers in space.
- *
- * Once a NULL value is found for a speaker position, no more speaker
- * positions will be used.
- *
- * Note that Y and Z are switched to translate from Miles's coordinate system.
- */
-void MilesAudioManager::
-set_speaker_configuration(LVecBase3 *speaker1, LVecBase3 *speaker2, LVecBase3 *speaker3, LVecBase3 *speaker4, LVecBase3 *speaker5, LVecBase3 *speaker6, LVecBase3 *speaker7, LVecBase3 *speaker8, LVecBase3 *speaker9) {
-  audio_debug("MilesAudioManager::set_speaker_configuration()");
-
-  GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
-
-  MSSVECTOR3D speakers[9];
-
-  if(speaker1 != nullptr) {
-    speakers[0].x = speaker1->get_x();
-    speakers[0].y = speaker1->get_z();
-    speakers[0].z = speaker1->get_y();
-  }
-  if(speaker2 != nullptr) {
-    speakers[1].x = speaker2->get_x();
-    speakers[1].y = speaker2->get_z();
-    speakers[1].z = speaker2->get_y();
-  }
-  if(speaker3 != nullptr) {
-    speakers[2].x = speaker3->get_x();
-    speakers[2].y = speaker3->get_z();
-    speakers[2].z = speaker3->get_y();
-  }
-  if(speaker4 != nullptr) {
-    speakers[3].x = speaker4->get_x();
-    speakers[3].y = speaker4->get_z();
-    speakers[3].z = speaker4->get_y();
-  }
-  if(speaker5 != nullptr) {
-    speakers[4].x = speaker5->get_x();
-    speakers[4].y = speaker5->get_z();
-    speakers[4].z = speaker5->get_y();
-  }
-  if(speaker6 != nullptr) {
-    speakers[5].x = speaker6->get_x();
-    speakers[5].y = speaker6->get_z();
-    speakers[5].z = speaker6->get_y();
-  }
-  if(speaker7 != nullptr) {
-    speakers[6].x = speaker7->get_x();
-    speakers[6].y = speaker7->get_z();
-    speakers[6].z = speaker7->get_y();
-  }
-  if(speaker8 != nullptr) {
-    speakers[7].x = speaker8->get_x();
-    speakers[7].y = speaker8->get_z();
-    speakers[7].z = speaker8->get_y();
-  }
-  if(speaker9 != nullptr) {
-    speakers[8].x = speaker9->get_x();
-    speakers[8].y = speaker9->get_z();
-    speakers[8].z = speaker9->get_y();
-  }
-
-  if(speaker1 == nullptr) {
-    audio_error("No valid speaker positions specified in MilesAudioManager::set_speaker_configuration().");
-  } else if(speaker2 == nullptr) {
-    AIL_set_speaker_configuration(mgr->_digital_driver, speakers, 1, 1.0);
-  } else if(speaker3 == nullptr) {
-    AIL_set_speaker_configuration(mgr->_digital_driver, speakers, 2, 1.0);
-  } else if(speaker4 == nullptr) {
-    AIL_set_speaker_configuration(mgr->_digital_driver, speakers, 3, 1.0);
-  } else if(speaker5 == nullptr) {
-    AIL_set_speaker_configuration(mgr->_digital_driver, speakers, 4, 1.0);
-  } else if(speaker6 == nullptr) {
-    AIL_set_speaker_configuration(mgr->_digital_driver, speakers, 5, 1.0);
-  } else if(speaker7 == nullptr) {
-    AIL_set_speaker_configuration(mgr->_digital_driver, speakers, 6, 1.0);
-  } else if(speaker8 == nullptr) {
-    AIL_set_speaker_configuration(mgr->_digital_driver, speakers, 7, 1.0);
-  } else if(speaker9 == nullptr) {
-    AIL_set_speaker_configuration(mgr->_digital_driver, speakers, 8, 1.0);
-  } else {
-    AIL_set_speaker_configuration(mgr->_digital_driver, speakers, 9, 1.0);
-  }
-}
-
-/**
- * Must be called every frame.  Failure to call this every frame could cause
- * problems for some audio managers.
- */
-void MilesAudioManager::
-update() {
-  {
-    MutexHolder holder(_streams_lock);
-    if (_stream_thread.is_null() && !_streams.empty()) {
-      // If we don't have a sub-thread, we have to service the streams in the
-      // main thread.
-      do_service_streams();
-    }
-  }
-
-  if (_sounds_finished) {
-    _sounds_finished = false;
-
-    // If the _sounds_finished flag was set, we should scan our list of
-    // playing sounds and see if any of them have finished recently.  We don't
-    // do this in the finished callback, because that might have been called
-    // in a sub-thread (and we may not have threading supported--and mutex
-    // protection--compiled in).
-
-    SoundsPlaying::iterator si = _sounds_playing.begin();
-    while (si != _sounds_playing.end()) {
-      MilesAudioSound *sound = (*si);
-      ++si;
-
-      if (sound->status() == AudioSound::READY) {
-        sound->stop();
-      }
-    }
-  }
-}
-
-/**
- *
- */
-void MilesAudioManager::
-release_sound(MilesAudioSound *audioSound) {
-  audio_debug("MilesAudioManager::release_sound(audioSound=\""
-              <<audioSound->get_name()<<"\"), this = " << (void *)this);
-  LightReMutexHolder holder(_lock);
-  AudioSet::iterator ai = _sounds_on_loan.find(audioSound);
-  if (ai != _sounds_on_loan.end()) {
-    _sounds_on_loan.erase(ai);
-  }
-
-  audio_debug("MilesAudioManager::release_sound() finished");
-}
-
-/**
- * Shuts down the audio manager and releases any resources associated with it.
- * Also cleans up all AudioSounds created via the manager.
- */
-void MilesAudioManager::
-cleanup() {
-  audio_debug("MilesAudioManager::cleanup(), this = " << (void *)this
-              << ", _cleanup_required = " << _cleanup_required);
-  LightReMutexHolder holder(_lock);
-  if (!_cleanup_required) {
-    return;
-  }
-
-  // Be sure to cleanup associated sounds before cleaning up the manager:
-  AudioSet orig_sounds;
-  orig_sounds.swap(_sounds_on_loan);
-  AudioSet::iterator ai;
-  for (ai = orig_sounds.begin(); ai != orig_sounds.end(); ++ai) {
-    (*ai)->cleanup();
-  }
-
-  do_clear_cache();
-
-  // Now stop the thread, if it has been started.
-  if (!_stream_thread.is_null()) {
-    milesAudio_cat.info()
-      << "Stopping audio streaming thread.\n";
-    PT(StreamThread) old_thread;
-    {
-      MutexHolder holder(_streams_lock);
-      nassertv(!_stream_thread.is_null());
-      _stream_thread->_keep_running = false;
-      _streams_cvar.notify();
-      old_thread = _stream_thread;
-      _stream_thread.clear();
-    }
-    old_thread->join();
-  }
-
-  _cleanup_required = false;
-  audio_debug("MilesAudioManager::cleanup() finished");
-}
-
-/**
- *
- */
-void MilesAudioManager::
-output(std::ostream &out) const {
-  LightReMutexHolder holder(_lock);
-  out << get_type() << ": " << _sounds_playing.size()
-      << " / " << _sounds_on_loan.size() << " sounds playing / total";
-}
-
-/**
- *
- */
-void MilesAudioManager::
-write(std::ostream &out) const {
-  LightReMutexHolder holder(_lock);
-
-  out << (*this) << "\n";
-  AudioSet::const_iterator ai;
-  for (ai = _sounds_on_loan.begin(); ai != _sounds_on_loan.end(); ++ai) {
-    MilesAudioSound *sound = (*ai);
-    out << "  " << *sound << "\n";
-  }
-
-  size_t total_preload = 0;
-  size_t num_preloaded = 0;
-  SoundMap::const_iterator si;
-  for (si = _sounds.begin(); si != _sounds.end(); ++si) {
-    if (!(*si).second->_raw_data.empty()) {
-      ++num_preloaded;
-      total_preload += (*si).second->_raw_data.size();
-    }
-  }
-  out << num_preloaded << " of " << _sounds.size() << " sounds preloaded, size used is " << (total_preload + 1023) / 1024 << "K\n";
-
-  {
-    MutexHolder holder(_streams_lock);
-    out << _streams.size() << " streams opened.\n";
-    if (!_stream_thread.is_null()) {
-      out << "(Audio streaming thread has been started.)\n";
-    }
-  }
-
-  GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
-
-  int num_samples = mgr->get_num_samples();
-  out << num_samples << " sample handles allocated globally.\n";
-
-  int num_sequences = mgr->get_num_sequences();
-  out << num_sequences << " sequence handles allocated globally.\n";
-}
-
-
-/**
- * Implementation of is_valid().  Assumes the lock is already held.
- */
-bool MilesAudioManager::
-do_is_valid() {
-  bool check = true;
-  if (_sounds.size() != _lru.size()) {
-    audio_debug("-- Error _sounds.size() != _lru.size() --");
-    check = false;
-
-  } else {
-    LRU::const_iterator i = _lru.begin();
-    for (; i != _lru.end(); ++i) {
-      SoundMap::const_iterator smi = _sounds.find(**i);
-      if (smi == _sounds.end()) {
-        audio_debug("-- "<<**i<<" in _lru and not in _sounds --");
-        check = false;
-        break;
-      }
-    }
-  }
-  return _is_valid && check;
-}
-
-/**
- * Assumes the lock is already held.
- */
-void MilesAudioManager::
-do_reduce_sounds_playing_to(unsigned int count) {
-  int limit = _sounds_playing.size() - count;
-  while (limit-- > 0) {
-    SoundsPlaying::iterator sound = _sounds_playing.begin();
-    assert(sound != _sounds_playing.end());
-    (**sound).stop();
-  }
-}
-
-/**
- * Assumes the lock is already held.
- */
-void MilesAudioManager::
-do_clear_cache() {
-  if (_is_valid) { nassertv(do_is_valid()); }
-  _sounds.clear();
-  _lru.clear();
-  if (_is_valid) { nassertv(do_is_valid()); }
-}
-
-/**
- * Adds the indicated stream to the list of streams to be serviced by a Panda
- * sub-thread.  This is in lieu of Miles' auto-service-stream mechanism.
- */
-void MilesAudioManager::
-start_service_stream(HSTREAM stream) {
-  MutexHolder holder(_streams_lock);
-  nassertv(find(_streams.begin(), _streams.end(), stream) == _streams.end());
-  _streams.push_back(stream);
-  _streams_cvar.notify();
-
-  if (_stream_thread.is_null() && Thread::is_threading_supported()) {
-    milesAudio_cat.info()
-      << "Starting audio streaming thread.\n";
-    _stream_thread = new StreamThread(this);
-    _stream_thread->start(TP_low, true);
-  }
-}
-
-/**
- * Removes the indicated stream from the list of streams to be serviced by a
- * Panda sub-thread.
- */
-void MilesAudioManager::
-stop_service_stream(HSTREAM stream) {
-  MutexHolder holder(_streams_lock);
-  Streams::iterator si = find(_streams.begin(), _streams.end(), stream);
-  if (si != _streams.end()) {
-    _streams.erase(si);
-  }
-}
-
-
-/**
- * Assumes the lock is already held.
- */
-void MilesAudioManager::
-most_recently_used(const string &path) {
-  audio_debug("MilesAudioManager::most_recently_used(path=\""
-      <<path<<"\")");
-  LRU::iterator i=find(_lru.begin(), _lru.end(), &path);
-  if (i != _lru.end()) {
-    _lru.erase(i);
-  }
-  // At this point, path should not exist in the _lru:
-  assert(find(_lru.begin(), _lru.end(), &path) == _lru.end());
-  _lru.push_back(&path);
-  nassertv(do_is_valid());
-}
-
-/**
- * Assumes the lock is already held.
- */
-void MilesAudioManager::
-uncache_a_sound() {
-  audio_debug("MilesAudioManager::uncache_a_sound()");
-  nassertv(do_is_valid());
-  // uncache least recently used:
-  assert(_lru.size()>0);
-  LRU::reference path=_lru.front();
-  SoundMap::iterator i = _sounds.find(*path);
-  assert(i != _sounds.end());
-  _lru.pop_front();
-
-  if (i != _sounds.end()) {
-    audio_debug("  uncaching \""<<i->first<<"\"");
-    _sounds.erase(i);
-  }
-  nassertv(do_is_valid());
-}
-
-/**
- * Inform the manager that a sound is about to play.
- */
-void MilesAudioManager::
-starting_sound(MilesAudioSound *audio) {
-  LightReMutexHolder holder(_lock);
-  if (_concurrent_sound_limit) {
-    do_reduce_sounds_playing_to(_concurrent_sound_limit);
-  }
-  _sounds_playing.insert(audio);
-}
-
-/**
- * Inform the manager that a sound is finished or someone called stop on the
- * sound (this should not be called if a sound is only paused).
- */
-void MilesAudioManager::
-stopping_sound(MilesAudioSound *audio) {
-  LightReMutexHolder holder(_lock);
-  _sounds_playing.erase(audio);
-  if (_hasMidiSounds && _sounds_playing.size() == 0) {
-    GlobalMilesManager::get_global_ptr()->force_midi_reset();
-  }
-}
-
-/**
- * Reads a sound file and allocates a SoundData pointer for it.  Returns NULL
- * if the sound file cannot be loaded.
- *
- * Assumes the lock is already held.
- */
-PT(MilesAudioManager::SoundData) MilesAudioManager::
-load(const Filename &file_name) {
-  PT(SoundData) sd = new SoundData;
-
-  VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
-  PT(VirtualFile) file = vfs->get_file(file_name);
-  if (file == nullptr) {
-    milesAudio_cat.warning()
-      << "No such file: " << file_name << "\n";
-    return nullptr;
-  }
-
-  if (file->get_file_size() == 0) {
-    milesAudio_cat.warning()
-      << "File " << file_name << " is empty\n";
-    return nullptr;
-  }
-
-  sd->_basename = file_name.get_basename();
-
-  string extension = sd->_basename.get_extension();
-  if (extension == "pz" || extension == "gz") {
-    extension = Filename(sd->_basename.get_basename_wo_extension()).get_extension();
-  }
-
-  bool is_midi_file = (downcase(extension) == "mid");
-
-  if ((miles_audio_preload_threshold == -1 || file->get_file_size() < (std::streamsize)miles_audio_preload_threshold) ||
-      is_midi_file) {
-    // If the file is sufficiently small, we'll preload it into memory.  MIDI
-    // files cannot be streamed, so we always preload them, regardless of
-    // size.
-
-    if (!file->read_file(sd->_raw_data, true)) {
-      milesAudio_cat.warning()
-        << "Unable to read " << file_name << "\n";
-      return nullptr;
-    }
-
-    sd->_file_type =
-      AIL_file_type(&sd->_raw_data[0], sd->_raw_data.size());
-
-    if (sd->_file_type == AILFILETYPE_MIDI) {
-      // A standard MIDI file.  We have to convert this to XMIDI for Miles.
-      void *xmi;
-      U32 xmi_size;
-      if (AIL_MIDI_to_XMI(&sd->_raw_data[0], sd->_raw_data.size(),
-                          &xmi, &xmi_size, 0)) {
-        audio_debug("converted " << sd->_basename << " from standard MIDI ("
-                    << sd->_raw_data.size() << " bytes) to XMIDI ("
-                    << xmi_size << " bytes)");
-
-        // Copy the data to our own buffer and free the Miles-allocated data.
-        sd->_raw_data.clear();
-        sd->_raw_data.insert(sd->_raw_data.end(),
-                             (unsigned char *)xmi, (unsigned char *)xmi + xmi_size);
-        AIL_mem_free_lock(xmi);
-        sd->_file_type = AILFILETYPE_XMIDI;
-      } else {
-        milesAudio_cat.warning()
-          << "Could not convert " << sd->_basename << " to XMIDI.\n";
-      }
-    }
-
-    bool expand_to_wav = false;
-
-    if (sd->_file_type != AILFILETYPE_MPEG_L3_AUDIO) {
-      audio_debug(sd->_basename << " is not an mp3 file.");
-    } else if ((int)sd->_raw_data.size() >= miles_audio_expand_mp3_threshold) {
-      audio_debug(sd->_basename << " is too large to expand in-memory.");
-    } else {
-      audio_debug(sd->_basename << " will be expanded in-memory.");
-      expand_to_wav = true;
-    }
-
-    if (expand_to_wav) {
-      // Now convert the file to WAV format in-memory.  This is useful to work
-      // around seek and length problems associated with variable bit-rate MP3
-      // encoding.
-      void *wav_data;
-      U32 wav_data_size;
-      if (AIL_decompress_ASI(&sd->_raw_data[0], sd->_raw_data.size(),
-                             sd->_basename.c_str(), &wav_data, &wav_data_size,
-                             nullptr)) {
-        audio_debug("expanded " << sd->_basename << " from " << sd->_raw_data.size()
-                    << " bytes to " << wav_data_size << " bytes.");
-
-        if (wav_data_size != 0) {
-          // Now copy the memory into our own buffers, and free the Miles-
-          // allocated memory.
-          sd->_raw_data.clear();
-          sd->_raw_data.insert(sd->_raw_data.end(),
-                               (unsigned char *)wav_data, (unsigned char *)wav_data + wav_data_size);
-          sd->_file_type = AILFILETYPE_PCM_WAV;
-          sd->_basename.set_extension("wav");
-        }
-        AIL_mem_free_lock(wav_data);
-
-      } else {
-        audio_debug("unable to expand " << sd->_basename);
-      }
-    }
-
-  } else {
-    // If the file is large, we'll stream it from disk instead of preloading
-    // it.  This means we don't need to load any data at this point.
-  }
-
-  return sd;
-}
-
-/**
- * Called to service the streaming audio channels currently playing on the
- * audio manager.
- */
-void MilesAudioManager::
-thread_main(volatile bool &keep_running) {
-  MutexHolder holder(_streams_lock);
-
-  while (keep_running) {
-    if (_streams.empty()) {
-      // If there are no streams to service, block on the condition variable.
-      _streams_cvar.wait();
-    } else {
-      do_service_streams();
-    }
-
-    // Now yield to be polite to the main application.
-    _streams_lock.release();
-    Thread::force_yield();
-    _streams_lock.acquire();
-  }
-}
-
-/**
- * Internal function to service all the streams.  Assumes _streams_lock is
- * already held.
- */
-void MilesAudioManager::
-do_service_streams() {
-  size_t i = 0;
-  while (i < _streams.size()) {
-    HSTREAM stream = _streams[i];
-
-    // We must release the lock while we are servicing stream i.
-    _streams_lock.release();
-    AIL_service_stream(stream, 0);
-    Thread::consider_yield();
-    _streams_lock.acquire();
-
-    ++i;
-  }
-}
-
-/**
- *
- */
-MilesAudioManager::StreamThread::
-StreamThread(MilesAudioManager *mgr) :
-  Thread("StreamThread", "StreamThread"),
-  _mgr(mgr)
-{
-  _keep_running = true;
-}
-
-/**
- *
- */
-void MilesAudioManager::StreamThread::
-thread_main() {
-  _mgr->thread_main(_keep_running);
-}
-
-/**
- *
- */
-MilesAudioManager::SoundData::
-SoundData() :
-  _raw_data(MilesAudioManager::get_class_type()),
-  _has_length(false),
-  _length(0.0f)
-{
-}
-
-/**
- *
- */
-MilesAudioManager::SoundData::
-~SoundData() {
-}
-
-/**
- *
- */
-PN_stdfloat MilesAudioManager::SoundData::
-get_length() {
-  if (!_has_length) {
-    // Time to determine the length of the file.
-
-    if (_raw_data.empty()) {
-      _length = 0.0f;
-      _has_length = true;
-
-    } else if (_file_type == AILFILETYPE_MPEG_L3_AUDIO) {
-      // If it's an mp3 file, we have to calculate its length by walking
-      // through all of its frames.
-      audio_debug("Computing length of mp3 file " << _basename);
-
-      MP3_INFO info;
-      AIL_inspect_MP3(&info, &_raw_data[0], _raw_data.size());
-      _length = 0.0f;
-      while (AIL_enumerate_MP3_frames(&info)) {
-        _length += info.data_size * 8.0f / info.bit_rate;
-      }
-      _has_length = true;
-
-    } else if (_file_type == AILFILETYPE_PCM_WAV ||
-               _file_type == AILFILETYPE_ADPCM_WAV ||
-               _file_type == AILFILETYPE_OTHER_ASI_WAV) {
-      audio_debug("Getting length of wav file " << _basename);
-
-      AILSOUNDINFO info;
-      if (AIL_WAV_info(&_raw_data[0], &info)) {
-        _length = (PN_stdfloat)info.samples / (PN_stdfloat)info.rate;
-        audio_debug(info.samples << " samples at " << info.rate
-                    << "; length is " << _length << " seconds.");
-        _has_length = true;
-      }
-    }
-  }
-
-  nassertr(_has_length, 0.0f);
-  return _length;
-}
-
-/**
- * Records the sample length, as determined externally.
- */
-void MilesAudioManager::SoundData::
-set_length(PN_stdfloat length) {
-  _length = length;
-  _has_length = true;
-}
-
-#endif //]

+ 0 - 198
panda/src/audiotraits/milesAudioManager.h

@@ -1,198 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file milesAudioManager.h
- * @author skyler
- * @date 2001-06-06
- * Prior system by: cary
- */
-
-#ifndef __MILES_AUDIO_MANAGER_H__ //[
-#define __MILES_AUDIO_MANAGER_H__
-
-#include "pandabase.h"
-#ifdef HAVE_RAD_MSS //[
-
-#include "audioManager.h"
-#include "pset.h"
-#include "pmap.h"
-#include "pdeque.h"
-#include "pvector.h"
-#include "thread.h"
-#include "pmutex.h"
-#include "lightReMutex.h"
-#include "conditionVar.h"
-#include "vector_uchar.h"
-
-#include <mss.h>
-
-class MilesAudioSound;
-
-class EXPCL_MILES_AUDIO MilesAudioManager: public AudioManager {
-public:
-  // See AudioManager.h for documentation.
-
-  MilesAudioManager();
-  virtual ~MilesAudioManager();
-
-  virtual void shutdown();
-
-  virtual bool is_valid();
-
-  virtual PT(AudioSound) get_sound(const Filename &file_name, bool positional = false, int mode=SM_heuristic);
-  virtual PT(AudioSound) get_sound(MovieAudio *sound, bool positional = false, int mode=SM_heuristic);
-  virtual void uncache_sound(const Filename &file_name);
-  virtual void clear_cache();
-  virtual void set_cache_limit(unsigned int count);
-  virtual unsigned int get_cache_limit() const;
-
-  virtual void set_volume(PN_stdfloat volume);
-  virtual PN_stdfloat get_volume() const;
-
-  void set_play_rate(PN_stdfloat play_rate);
-  PN_stdfloat get_play_rate() const;
-
-  virtual void set_active(bool active);
-  virtual bool get_active() const;
-
-  virtual void set_concurrent_sound_limit(unsigned int limit = 0);
-  virtual unsigned int get_concurrent_sound_limit() const;
-
-  virtual void reduce_sounds_playing_to(unsigned int count);
-  virtual void stop_all_sounds();
-
-  virtual void update();
-
-  // Tell the manager that the sound dtor was called.
-  void release_sound(MilesAudioSound *audioSound);
-  void cleanup();
-
-  // 3D spatialized sound support.  Spatialized sound was originally added for
-  // FMOD, so there are parts of the interface in the Miles implementation
-  // that are a little more awkward than they would be otherwise.
-  virtual void audio_3d_set_listener_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, PN_stdfloat vx, PN_stdfloat xy, PN_stdfloat xz, PN_stdfloat fx, PN_stdfloat fy, PN_stdfloat fz, PN_stdfloat ux, PN_stdfloat uy, PN_stdfloat uz);
-  virtual void audio_3d_get_listener_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz, PN_stdfloat *fx, PN_stdfloat *fy, PN_stdfloat *fz, PN_stdfloat *ux, PN_stdfloat *uy, PN_stdfloat *uz);
-  virtual void audio_3d_set_distance_factor(PN_stdfloat factor);
-  virtual PN_stdfloat audio_3d_get_distance_factor() const;
-  virtual void audio_3d_set_doppler_factor(PN_stdfloat factor);
-  virtual PN_stdfloat audio_3d_get_doppler_factor() const;
-  virtual void audio_3d_set_drop_off_factor(PN_stdfloat factor);
-  virtual PN_stdfloat audio_3d_get_drop_off_factor() const;
-  virtual void set_speaker_configuration(LVecBase3 *speaker1, LVecBase3 *speaker2=nullptr, LVecBase3 *speaker3=nullptr, LVecBase3 *speaker4=nullptr, LVecBase3 *speaker5=nullptr, LVecBase3 *speaker6=nullptr, LVecBase3 *speaker7=nullptr, LVecBase3 *speaker8=nullptr, LVecBase3 *speaker9=nullptr);
-
-  virtual void output(std::ostream &out) const;
-  virtual void write(std::ostream &out) const;
-
-private:
-  bool do_is_valid();
-  void do_reduce_sounds_playing_to(unsigned int count);
-  void do_clear_cache();
-
-  void start_service_stream(HSTREAM stream);
-  void stop_service_stream(HSTREAM stream);
-
-  void most_recently_used(const std::string &path);
-  void uncache_a_sound();
-
-  void starting_sound(MilesAudioSound *audio);
-  void stopping_sound(MilesAudioSound *audio);
-
-  class SoundData;
-  PT(SoundData) load(const Filename &file_name);
-
-  void thread_main(volatile bool &keep_running);
-  void do_service_streams();
-
-private:
-  class StreamThread : public Thread {
-  public:
-    StreamThread(MilesAudioManager *mgr);
-    virtual void thread_main();
-
-    MilesAudioManager *_mgr;
-    volatile bool _keep_running;
-  };
-
-  // The sound cache:
-  class SoundData : public ReferenceCount {
-  public:
-    SoundData();
-    ~SoundData();
-    PN_stdfloat get_length();
-    void set_length(PN_stdfloat length);
-
-    Filename _basename;
-    S32 _file_type;
-    vector_uchar _raw_data;
-    bool _has_length;
-    PN_stdfloat _length;  // in seconds.
-  };
-  typedef pmap<std::string, PT(SoundData) > SoundMap;
-  SoundMap _sounds;
-
-  typedef pset<MilesAudioSound *> AudioSet;
-  // The offspring of this manager:
-  AudioSet _sounds_on_loan;
-
-  typedef pset<MilesAudioSound *> SoundsPlaying;
-  // The sounds from this manager that are currently playing:
-  SoundsPlaying _sounds_playing;
-
-  // The Least Recently Used mechanism:
-  typedef pdeque<const std::string *> LRU;
-  LRU _lru;
-  // State:
-  PN_stdfloat _volume;
-  PN_stdfloat _play_rate;
-  bool _active;
-  int _cache_limit;
-  bool _cleanup_required;
-  unsigned int _concurrent_sound_limit;
-
-  bool _is_valid;
-  bool _hasMidiSounds;
-
-  // This mutex protects everything above.
-  LightReMutex _lock;
-  bool _sounds_finished;
-
-  typedef pvector<HSTREAM> Streams;
-  PT(StreamThread) _stream_thread;
-  Streams _streams;
-  Mutex _streams_lock;
-  ConditionVar _streams_cvar;
-
-public:
-  static TypeHandle get_class_type() {
-    return _type_handle;
-  }
-  static void init_type() {
-    AudioManager::init_type();
-    register_type(_type_handle, "MilesAudioManager",
-                  AudioManager::get_class_type());
-  }
-  virtual TypeHandle get_type() const {
-    return get_class_type();
-  }
-  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
-
-private:
-  static TypeHandle _type_handle;
-
-  friend class MilesAudioSound;
-  friend class MilesAudioSample;
-  friend class MilesAudioSequence;
-  friend class MilesAudioStream;
-};
-
-EXPCL_MILES_AUDIO AudioManager *Create_MilesAudioManager();
-
-
-#endif //]
-
-#endif //]

+ 0 - 13
panda/src/audiotraits/milesAudioSample.I

@@ -1,13 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file milesAudioSample.I
- * @author skyler
- * @date 2001-06-06
- * Prior system by: cary
- */

+ 0 - 530
panda/src/audiotraits/milesAudioSample.cxx

@@ -1,530 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file milesAudioSample.cxx
- * @author skyler
- * @date 2001-06-06
- */
-
-#include "milesAudioSample.h"
-
-#ifdef HAVE_RAD_MSS //[
-
-#include "milesAudioManager.h"
-
-
-TypeHandle MilesAudioSample::_type_handle;
-
-#undef miles_audio_debug
-
-#ifndef NDEBUG //[
-#define miles_audio_debug(x) \
-    audio_debug("MilesAudioSample \""<<get_name()<<"\" "<< x )
-#else //][
-#define miles_audio_debug(x) ((void)0)
-#endif //]
-
-/**
- * This constructor is called only by the MilesAudioManager.
- */
-MilesAudioSample::
-MilesAudioSample(MilesAudioManager *manager, MilesAudioManager::SoundData *sd,
-                 const std::string &file_name) :
-  MilesAudioSound(manager, file_name),
-  _sd(sd)
-{
-  nassertv(sd != nullptr);
-  audio_debug("MilesAudioSample(manager=0x"<<(void*)&manager
-              <<", sd=0x"<<(void*)sd<<", file_name="<<file_name<<")");
-
-  _sample = 0;
-  _sample_index = 0;
-  _original_playback_rate = 1.0f;
-}
-
-/**
- *
- */
-MilesAudioSample::
-~MilesAudioSample() {
-  miles_audio_debug("~MilesAudioSample()");
-  cleanup();
-  miles_audio_debug("~MilesAudioSample() done");
-}
-
-/**
- *
- */
-void MilesAudioSample::
-play() {
-  miles_audio_debug("play()");
-  if (_active) {
-    if (_sd->_raw_data.empty()) {
-      milesAudio_cat.warning()
-        << "Could not play " << _file_name << ": no data\n";
-    } else {
-      stop();
-      _manager->starting_sound(this);
-
-      nassertv(_sample == 0);
-
-      GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
-      if (!mgr->get_sample(_sample, _sample_index, this)){
-        milesAudio_cat.warning()
-          << "Could not play " << _file_name << ": too many open samples\n";
-        _sample = 0;
-      } else {
-        AIL_set_named_sample_file(_sample, _sd->_basename.c_str(),
-                                  &_sd->_raw_data[0], _sd->_raw_data.size(),
-                                  0);
-        _original_playback_rate = AIL_sample_playback_rate(_sample);
-        AIL_set_sample_user_data(_sample, 0, (SINTa)this);
-        AIL_register_EOS_callback(_sample, finish_callback);
-
-        set_volume(_volume);
-        set_play_rate(_play_rate);
-        AIL_set_sample_loop_count(_sample, _loop_count);
-
-        if (_got_start_time) {
-          do_set_time(_start_time);
-          AIL_resume_sample(_sample);
-        } else {
-          AIL_start_sample(_sample);
-        }
-      }
-
-      _got_start_time = false;
-    }
-  } else {
-    // In case _loop_count gets set to forever (zero):
-    audio_debug("  paused "<<_file_name );
-    _paused = true;
-  }
-}
-
-/**
- *
- */
-void MilesAudioSample::
-stop() {
-  if (_manager == nullptr) {
-    return;
-  }
-
-  miles_audio_debug("stop()");
-  _manager->stopping_sound(this);
-  // The _paused flag should not be cleared here.  _paused is not like the
-  // Pause button on a cddvd player.  It is used as a flag to say that it was
-  // looping when it was set inactive.  There is no need to make this
-  // symmetrical with play().  set_active() is the 'owner' of _paused.  play()
-  // accesses _paused to help in the situation where someone calls play on an
-  // inactive sound().
-
-  // it fixes audio bug, I don't understand the reasoning of the above comment
-  _paused = false;
-
-  if (_sample != 0) {
-    AIL_end_sample(_sample);
-
-    GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
-    mgr->release_sample(_sample_index, this);
-
-    _sample = 0;
-    _sample_index = 0;
-  }
-}
-
-/**
- *
- */
-PN_stdfloat MilesAudioSample::
-get_time() const {
-  if (_sample == 0) {
-    if (_got_start_time) {
-      return _start_time;
-    }
-    return 0.0f;
-  }
-
-  S32 current_ms;
-  AIL_sample_ms_position(_sample, nullptr, &current_ms);
-  PN_stdfloat time = PN_stdfloat(current_ms * 0.001f);
-
-  return time;
-}
-
-/**
- *
- */
-void MilesAudioSample::
-set_volume(PN_stdfloat volume) {
-  miles_audio_debug("set_volume(volume="<<volume<<")");
-
-  // Set the volume even if our volume is not changing, because the
-  // MilesAudioManager will call set_volume() when *its* volume changes.
-
-  // Set the volume:
-  _volume = volume;
-
-  if (_sample != 0) {
-    volume *= _manager->get_volume();
-
-    // Change to Miles volume, range 0 to 1.0:
-    F32 milesVolume = volume;
-    milesVolume = std::min(milesVolume, 1.0f);
-    milesVolume = std::max(milesVolume, 0.0f);
-
-    // Convert balance of -1.0..1.0 to 0-1.0:
-    F32 milesBalance = (F32)((_balance + 1.0f) * 0.5f);
-
-    AIL_set_sample_volume_pan(_sample, milesVolume, milesBalance);
-  }
-}
-
-/**
- *
- */
-void MilesAudioSample::
-set_balance(PN_stdfloat balance_right) {
-  miles_audio_debug("set_balance(balance_right="<<balance_right<<")");
-  _balance = balance_right;
-
-  // Call set_volume to effect the change:
-  set_volume(_volume);
-}
-
-/**
- *
- */
-void MilesAudioSample::
-set_play_rate(PN_stdfloat play_rate) {
-  miles_audio_debug("set_play_rate(play_rate="<<play_rate<<")");
-
-  // Set the play_rate:
-  _play_rate = play_rate;
-
-  if (_sample != 0) {
-    play_rate *= _manager->get_play_rate();
-
-    // wave and mp3 use sample rate (e.g.  44100)
-    S32 speed = (S32)(play_rate * (PN_stdfloat)_original_playback_rate);
-    AIL_set_sample_playback_rate(_sample, speed);
-    audio_debug("  play_rate for this wav or mp3 is now " << speed);
-  }
-}
-
-/**
- *
- */
-PN_stdfloat MilesAudioSample::
-length() const {
-  return _sd->get_length();
-}
-
-/**
- *
- */
-AudioSound::SoundStatus MilesAudioSample::
-status() const {
-  if (_sample == 0) {
-    return AudioSound::READY;
-  }
-  switch (AIL_sample_status(_sample)) {
-  case SMP_DONE:
-  case SMP_STOPPED:
-  case SMP_FREE:
-    return AudioSound::READY;
-
-  case SMP_PLAYING:
-  case SMP_PLAYINGBUTRELEASED:
-    return AudioSound::PLAYING;
-
-  default:
-    return AudioSound::BAD;
-  }
-}
-
-/**
- * Stops the sound from playing and releases any associated resources, in
- * preparation for releasing the sound or shutting down the sound system.
- */
-void MilesAudioSample::
-cleanup() {
-  stop();
-  set_active(false);
-  nassertv(_sample == 0);
-
-  if (_manager != nullptr) {
-    _manager->release_sound(this);
-    _manager = nullptr;
-  }
-}
-
-/**
- *
- */
-void MilesAudioSample::
-output(std::ostream &out) const {
-  out << get_type() << " " << get_name() << " " << status();
-  if (!_sd.is_null()) {
-    out << " " << (_sd->_raw_data.size() + 1023) / 1024 << "K";
-  }
-}
-
-/**
- * Set position and velocity of this sound.  Note that Y and Z are switched to
- * translate from Miles's coordinate system.
- */
-void MilesAudioSample::set_3d_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, PN_stdfloat vx, PN_stdfloat vy, PN_stdfloat vz) {
-  audio_debug("MilesAudioSample::set_3d_attributes()  Setting a sound's 3D Coordinates.");
-
-  if(_sample != 0) {
-    AIL_set_sample_3D_position(_sample, px, pz, py);
-    AIL_set_sample_3D_velocity_vector(_sample, vx, vz, vy);
-  } else {
-    audio_warning("_sample == 0 in MilesAudioSample::set_3d_attributes().");
-  }
-}
-
-/**
- * Get position and velocity of this sound.
- */
-void MilesAudioSample::get_3d_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz) {
-  audio_debug("MilesAudioSample::get_3d_attributes().");
-
-  if(_sample != 0) {
-    float lpx, lpy, lpz, lvx, lvy, lvz;
-    AIL_sample_3D_position(_sample, &lpx, &lpz, &lpy);
-    AIL_sample_3D_velocity(_sample, &lvx, &lvz, &lvy);
-    *px = lpx;
-    *py = lpy;
-    *pz = lpz;
-    *vx = lvx;
-    *vy = lvy;
-    *vz = lvz;
-  } else {
-    audio_warning("_sample == 0 in MilesAudioSample::get_3d_attributes().");
-  }
-}
-
-/**
- * Set the distance that this sound begins to fall off.  With Miles's default
- * falloff behavior, when the distance between the sound and the listener is
- * doubled, the volume is halved, and vice versa.
- */
-void MilesAudioSample::set_3d_min_distance(PN_stdfloat dist) {
-  audio_debug("MilesAudioSample::set_3d_min_distance() Setting the sound's 3D min distance ( min= " << dist << " ) ");
-
-  if(_sample != 0) {
-    // Implementation is awkward, since Miles gets and sets min and max
-    // distances in a single operation.
-    float max_dist;
-    int auto_3D_wet_atten;
-    AIL_sample_3D_distances(_sample, &max_dist, nullptr, &auto_3D_wet_atten);
-
-    AIL_set_sample_3D_distances(_sample, max_dist, dist, auto_3D_wet_atten);
-  } else {
-    audio_warning("_sample == 0 in MilesAudioSample::set_3d_min_distance().");
-  }
-}
-
-/**
- * Get the distance that this sound begins to fall off.
- */
-PN_stdfloat MilesAudioSample::get_3d_min_distance() const {
-  audio_debug("MilesAudioSample::get_3d_min_distance() ");
-
-  if(_sample != 0) {
-    float min_dist;
-    AIL_sample_3D_distances(_sample, nullptr, &min_dist, nullptr);
-    return (PN_stdfloat)min_dist;
-  } else {
-    audio_warning("_sample == 0 in MilesAudioSample::get_3d_min_distance().");
-    return -1.0;
-  }
-}
-
-/**
- * Set the distance at which this sound is clipped to silence.  Note that this
- * value does not affect the rate at which the sound falls off, but only the
- * distance at which it gets clipped.
- */
-void MilesAudioSample::set_3d_max_distance(PN_stdfloat dist) {
-  audio_debug("MilesAudioSample::set_3d_max_distance() Setting the sound's 3D max distance ( max= " << dist << " ) ");
-
-  if(_sample != 0) {
-    // Implementation is awkward, since Miles gets and sets min and max
-    // distances in a single operation.
-    float min_dist;
-    int auto_3D_wet_atten;
-    AIL_sample_3D_distances(_sample, nullptr, &min_dist, &auto_3D_wet_atten);
-
-    AIL_set_sample_3D_distances(_sample, dist, min_dist, auto_3D_wet_atten);
-  } else {
-    audio_warning("_sample == 0 in MilesAudioSample::set_3d_max_distance().");
-  }
-}
-
-/**
- * Get the distance at which this sound is clipped to silence.
- */
-PN_stdfloat MilesAudioSample::get_3d_max_distance() const {
-  audio_debug("MilesAudioSample::get_3d_max_distance() ");
-
-  if(_sample != 0) {
-    float max_dist;
-    AIL_sample_3D_distances(_sample, &max_dist, nullptr, nullptr);
-    return (PN_stdfloat)max_dist;
-  } else {
-    audio_warning("_sample == 0 in MilesAudioSample::get_3d_max_distance().");
-    return -1.0;
-  }
-}
-
-/**
- * Get the level of a particular logical channel (speaker). "index" specifies
- * which speaker in an array of all the logical channels currently in use to
- * retrieve the level of.
- *
- * For instance, in a standard 4.0 channel setup, speakers are setup as
- * [frontLeft, frontRight, backLeft, backRight]. Thus, get_speaker_level(2)
- * will retrieve the level of the backLeft speaker.
- *
- * The order in which speakers appear in the array for standard speaker setups
- * is defined to be:
- *
- * FRONT_LEFT FRONT_RIGHT FRONT_CENTER LOW_FREQUENCY (sub woofer) BACK_LEFT
- * BACK_RIGHT FRONT_LEFT_OF_CENTER FRONT_RIGHT_OF_CENTER BACK_CENTER SIDE_LEFT
- * SIDE_RIGHT TOP_CENTER TOP_FRONT_LEFT TOP_FRONT_CENTER TOP_FRONT_RIGHT
- * TOP_BACK_LEFT TOP_BACK_CENTER TOP_BACK_RIGHT
- *
- */
-PN_stdfloat MilesAudioSample::
-get_speaker_level(int index) {
-  audio_debug("MilesAudioSample::get_speaker_level(" << index << ")");
-
-  if(_sample != 0) {
-    int numLevels;
-    float *levels = AIL_sample_channel_levels(_sample, &numLevels);
-
-    if(index < numLevels) {
-      return (PN_stdfloat)levels[index];
-    } else {
-      audio_error("index out of range in MilesAudioSample::get_speaker_level.  numLevels: " << numLevels);
-      return -1.0;
-    }
-  } else {
-    audio_warning("Warning: MilesAudioSample::get_speaker_level only works for sounds that are currently playing");
-    return -1.0;
-  }
-}
-
-/**
- * Set the output levels on the logical channels (speakers) for this sound.
- * Values should be in the range 0.0 to 1.0. Levels for up to nine channels
- * may be specified.  As soon as a level is reached that falls outside the
- * range 0.0 to 1.0, the levels specified up to that point will be sent and
- * all other levels will be ignored.
- *
- * The user must know what the current speaker setup is in order to know which
- * level corresponds to which speaker.
- *
- * This method will have no effect if 3D attributes have been set for this
- * sound.
- *
- * The order in which speakers appear in the array for standard speaker setups
- * is defined to be:
- *
- * FRONT_LEFT FRONT_RIGHT FRONT_CENTER LOW_FREQUENCY (sub woofer) BACK_LEFT
- * BACK_RIGHT FRONT_LEFT_OF_CENTER FRONT_RIGHT_OF_CENTER BACK_CENTER SIDE_LEFT
- * SIDE_RIGHT TOP_CENTER TOP_FRONT_LEFT TOP_FRONT_CENTER TOP_FRONT_RIGHT
- * TOP_BACK_LEFT TOP_BACK_CENTER TOP_BACK_RIGHT
- *
- */
-void MilesAudioSample::
-set_speaker_levels(PN_stdfloat level1, PN_stdfloat level2, PN_stdfloat level3, PN_stdfloat level4, PN_stdfloat level5, PN_stdfloat level6, PN_stdfloat level7, PN_stdfloat level8, PN_stdfloat level9) {
-  audio_debug("MilesAudioSample::set_speaker_levels()");
-
-  if(_sample != 0) {
-    float levels[9] = {level1, level2, level3, level4, level5, level6, level7, level8, level9};
-
-    if((level1 < 0.0) || (level1 > 1.0)) {
-      audio_error("No valid levels specified in MilesAudioSample::set_speaker_levels().");
-    } else if((level2 < 0.0) || (level2 > 1.0)) {
-      AIL_set_sample_channel_levels(_sample, levels, 1);
-    } else if((level3 < 0.0) || (level3 > 1.0)) {
-      AIL_set_sample_channel_levels(_sample, levels, 2);
-    } else if((level4 < 0.0) || (level4 > 1.0)) {
-      AIL_set_sample_channel_levels(_sample, levels, 3);
-    } else if((level5 < 0.0) || (level5 > 1.0)) {
-      AIL_set_sample_channel_levels(_sample, levels, 4);
-    } else if((level6 < 0.0) || (level6 > 1.0)) {
-      AIL_set_sample_channel_levels(_sample, levels, 5);
-    } else if((level7 < 0.0) || (level7 > 1.0)) {
-      AIL_set_sample_channel_levels(_sample, levels, 6);
-    } else if((level8 < 0.0) || (level8 > 1.0)) {
-      AIL_set_sample_channel_levels(_sample, levels, 7);
-    } else if((level9 < 0.0) || (level9 > 1.0)) {
-      AIL_set_sample_channel_levels(_sample, levels, 8);
-    } else {
-      AIL_set_sample_channel_levels(_sample, levels, 9);
-    }
-  } else {
-    audio_warning("Warning: MilesAudioSample::set_speaker_levels only works for sounds that are currently playing");
-  }
-}
-
-/**
- * Called by the GlobalMilesManager when it is detected that this particular
- * sound has already stopped, and its sample handle will be recycled.
- */
-void MilesAudioSample::
-internal_stop() {
-  _sample = 0;
-  _sample_index = 0;
-}
-
-/**
- * This callback is made by Miles (possibly in a sub-thread) when the sample
- * finishes.
- */
-void AILCALLBACK MilesAudioSample::
-finish_callback(HSAMPLE sample) {
-  MilesAudioSample *self = (MilesAudioSample *)AIL_sample_user_data(sample, 0);
-  if (milesAudio_cat.is_debug()) {
-    milesAudio_cat.debug()
-      << "finished " << *self << "\n";
-  }
-  if (self->_manager == nullptr) {
-    return;
-  }
-  self->_manager->_sounds_finished = true;
-}
-
-/**
- * Sets the start time of an already allocated sample.
- */
-void MilesAudioSample::
-do_set_time(PN_stdfloat time) {
-  miles_audio_debug("do_set_time(time="<<time<<")");
-  nassertv(_sample != 0);
-
-  // Ensure we don't inadvertently run off the end of the sound.
-  PN_stdfloat max_time = length();
-  if (time > max_time) {
-    milesAudio_cat.warning()
-      << "set_time(" << time << ") requested for sound of length "
-      << max_time << "\n";
-    time = max_time;
-  }
-
-  S32 time_ms = (S32)(1000.0f * time);
-  AIL_set_sample_ms_position(_sample, time_ms);
-}
-
-#endif //]

+ 0 - 103
panda/src/audiotraits/milesAudioSample.h

@@ -1,103 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file milesAudioSample.h
- * @author skyler
- * @date 2001-06-06
- * Prior system by: cary
- */
-
-#ifndef MILESAUDIOSAMPLE_H
-#define MILESAUDIOSAMPLE_H
-
-#include "pandabase.h"
-#ifdef HAVE_RAD_MSS //[
-
-#include "milesAudioSound.h"
-#include "milesAudioManager.h"
-
-#include <mss.h>
-
-/**
- * A sound file, such as a WAV or MP3 file, that is preloaded into memory and
- * played from memory.
- */
-class EXPCL_MILES_AUDIO MilesAudioSample : public MilesAudioSound {
-private:
-  MilesAudioSample(MilesAudioManager *manager,
-                   MilesAudioManager::SoundData *sd,
-                   const std::string &file_name);
-
-public:
-  virtual ~MilesAudioSample();
-
-  virtual void play();
-  virtual void stop();
-
-  virtual PN_stdfloat get_time() const;
-
-  virtual void set_volume(PN_stdfloat volume=1.0f);
-  virtual void set_balance(PN_stdfloat balance_right=0.0f);
-  virtual void set_play_rate(PN_stdfloat play_rate=1.0f);
-
-  virtual PN_stdfloat length() const;
-
-  virtual AudioSound::SoundStatus status() const;
-
-  virtual void cleanup();
-  virtual void output(std::ostream &out) const;
-
-  // 3D spatialized sound support.  Spatialized sound was originally added for
-  // FMOD, so there are parts of the interface in the Miles implementation
-  // that are a little more awkward than they would be otherwise.
-  void set_3d_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, PN_stdfloat vx, PN_stdfloat vy, PN_stdfloat vz);
-  void get_3d_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz);
-  void set_3d_min_distance(PN_stdfloat dist);
-  PN_stdfloat get_3d_min_distance() const;
-  void set_3d_max_distance(PN_stdfloat dist);
-  PN_stdfloat get_3d_max_distance() const;
-
-  virtual PN_stdfloat get_speaker_level(int index);
-  virtual void set_speaker_levels(PN_stdfloat level1, PN_stdfloat level2=-1.0f, PN_stdfloat level3=-1.0f, PN_stdfloat level4=-1.0f, PN_stdfloat level5=-1.0f, PN_stdfloat level6=-1.0f, PN_stdfloat level7=-1.0f, PN_stdfloat level8=-1.0f, PN_stdfloat level9=-1.0f);
-
-private:
-  void internal_stop();
-  static void AILCALLBACK finish_callback(HSAMPLE sample);
-  void do_set_time(PN_stdfloat time);
-
-  PT(MilesAudioManager::SoundData) _sd;
-  HSAMPLE _sample;
-  size_t _sample_index;
-  S32 _original_playback_rate;
-
-public:
-  static TypeHandle get_class_type() {
-    return _type_handle;
-  }
-  static void init_type() {
-    MilesAudioSound::init_type();
-    register_type(_type_handle, "MilesAudioSample",
-                  MilesAudioSound::get_class_type());
-  }
-  virtual TypeHandle get_type() const {
-    return get_class_type();
-  }
-  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
-
-private:
-  static TypeHandle _type_handle;
-
-  friend class GlobalMilesManager;
-  friend class MilesAudioManager;
-};
-
-#include "milesAudioSample.I"
-
-#endif //]
-
-#endif  /* MILESAUDIOSAMPLE_H */

+ 0 - 12
panda/src/audiotraits/milesAudioSequence.I

@@ -1,12 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file milesAudioSequence.I
- * @author drose
- * @date 2007-07-31
- */

+ 0 - 331
panda/src/audiotraits/milesAudioSequence.cxx

@@ -1,331 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file milesAudioSequence.cxx
- * @author drose
- * @date 2007-07-31
- */
-
-#include "milesAudioSequence.h"
-
-#ifdef HAVE_RAD_MSS //[
-
-#include "milesAudioManager.h"
-
-
-TypeHandle MilesAudioSequence::_type_handle;
-
-#undef miles_audio_debug
-
-#ifndef NDEBUG //[
-#define miles_audio_debug(x) \
-    audio_debug("MilesAudioSequence \""<<get_name()<<"\" "<< x )
-#else //][
-#define miles_audio_debug(x) ((void)0)
-#endif //]
-
-/**
- * This constructor is called only by the MilesAudioManager.
- */
-MilesAudioSequence::
-MilesAudioSequence(MilesAudioManager *manager, MilesAudioManager::SoundData *sd,
-                 const std::string &file_name) :
-  MilesAudioSound(manager, file_name),
-  _sd(sd)
-{
-  nassertv(sd != nullptr);
-  audio_debug("MilesAudioSequence(manager=0x"<<(void*)&manager
-              <<", sd=0x"<<(void*)sd<<", file_name="<<file_name<<")");
-
-  _sequence = 0;
-  _sequence_index = 0;
-}
-
-/**
- *
- */
-MilesAudioSequence::
-~MilesAudioSequence() {
-  miles_audio_debug("~MilesAudioSequence()");
-  cleanup();
-  _manager->release_sound(this);
-  miles_audio_debug("~MilesAudioSequence() done");
-}
-
-/**
- *
- */
-void MilesAudioSequence::
-play() {
-  miles_audio_debug("play()");
-  if (_active) {
-    stop();
-
-    if (_sd->_raw_data.empty()) {
-      milesAudio_cat.warning()
-        << "Could not play " << _file_name << ": no data\n";
-    } else {
-      _manager->starting_sound(this);
-      nassertv(_sequence == 0);
-
-      GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
-      if (!mgr->get_sequence(_sequence, _sequence_index, this)){
-        milesAudio_cat.warning()
-          << "Could not play " << _file_name << ": too many open sequences\n";
-        _sequence = 0;
-      } else {
-        AIL_init_sequence(_sequence, &_sd->_raw_data[0], 0);
-        AIL_set_sequence_user_data(_sequence, 0, (SINTa)this);
-        AIL_register_sequence_callback(_sequence, finish_callback);
-
-        set_volume(_volume);
-        set_play_rate(_play_rate);
-        AIL_set_sequence_loop_count(_sequence, _loop_count);
-
-        if (_got_start_time) {
-          do_set_time(_start_time);
-          AIL_resume_sequence(_sequence);
-        } else {
-          AIL_start_sequence(_sequence);
-        }
-      }
-
-      _got_start_time = false;
-    }
-  } else {
-    // In case _loop_count gets set to forever (zero):
-    audio_debug("  paused "<<_file_name );
-    _paused = true;
-  }
-}
-
-/**
- *
- */
-void MilesAudioSequence::
-stop() {
-  miles_audio_debug("stop()");
-  _manager->stopping_sound(this);
-  // The _paused flag should not be cleared here.  _paused is not like the
-  // Pause button on a cddvd player.  It is used as a flag to say that it was
-  // looping when it was set inactive.  There is no need to make this
-  // symmetrical with play().  set_active() is the 'owner' of _paused.  play()
-  // accesses _paused to help in the situation where someone calls play on an
-  // inactive sound().
-
-  if (_sequence != 0) {
-    AIL_end_sequence(_sequence);
-
-    GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
-    mgr->release_sequence(_sequence_index, this);
-
-    _sequence = 0;
-    _sequence_index = 0;
-  }
-}
-
-/**
- *
- */
-PN_stdfloat MilesAudioSequence::
-get_time() const {
-  if (_sequence == 0) {
-    if (_got_start_time) {
-      return _start_time;
-    }
-    return 0.0f;
-  }
-
-  S32 current_ms;
-  AIL_sequence_ms_position(_sequence, nullptr, &current_ms);
-  PN_stdfloat time = PN_stdfloat(current_ms * 0.001f);
-
-  return time;
-}
-
-/**
- *
- */
-void MilesAudioSequence::
-set_volume(PN_stdfloat volume) {
-  miles_audio_debug("set_volume(volume="<<volume<<")");
-
-  // Set the volume even if our volume is not changing, because the
-  // MilesAudioManager will call set_volume() when *its* volume changes.
-
-  // Set the volume:
-  _volume = volume;
-
-  if (_sequence != 0) {
-    volume *= _manager->get_volume();
-
-    // Change to Miles volume, range 0 to 127:
-    S32 milesVolume = (S32)(volume * 127.0f);
-    milesVolume = std::min(milesVolume, 127);
-    milesVolume = std::max(milesVolume, 0);
-
-    AIL_set_sequence_volume(_sequence, milesVolume, 0);
-  }
-}
-
-/**
- *
- */
-void MilesAudioSequence::
-set_balance(PN_stdfloat balance_right) {
-  miles_audio_debug("set_balance(balance_right="<<balance_right<<")");
-  _balance = balance_right;
-
-  // Balance has no effect on a MIDI file.
-}
-
-/**
- *
- */
-void MilesAudioSequence::
-set_play_rate(PN_stdfloat play_rate) {
-  miles_audio_debug("set_play_rate(play_rate="<<play_rate<<")");
-
-  // Set the play_rate:
-  _play_rate = play_rate;
-
-  if (_sequence != 0) {
-    play_rate *= _manager->get_play_rate();
-
-    S32 percent = (S32)(play_rate * 100.0f);
-    AIL_set_sequence_tempo(_sequence, percent, 0);
-  }
-}
-
-/**
- *
- */
-PN_stdfloat MilesAudioSequence::
-length() const {
-  if (_sequence == 0) {
-    // The MIDI file hasn't been started yet.  See if the length is cached in
-    // the SoundData.
-    if (!_sd->_has_length) {
-      // It isn't cached, so load the sequence temporarily to determine its
-      // length.
-      ((MilesAudioSequence *)this)->determine_length();
-    }
-
-    return _sd->get_length();
-  }
-
-  // The MIDI file has already been started, so we can ask it directly.
-  S32 length_ms;
-  AIL_sequence_ms_position(_sequence, &length_ms, nullptr);
-  PN_stdfloat time = (PN_stdfloat)length_ms * 0.001f;
-  return time;
-}
-
-/**
- *
- */
-AudioSound::SoundStatus MilesAudioSequence::
-status() const {
-  if (_sequence == 0) {
-    return AudioSound::READY;
-  }
-  switch (AIL_sequence_status(_sequence)) {
-  case SEQ_DONE:
-  case SEQ_STOPPED:
-  case SEQ_FREE:
-    return AudioSound::READY;
-
-  case SEQ_PLAYING:
-  case SEQ_PLAYINGBUTRELEASED:
-    return AudioSound::PLAYING;
-
-  default:
-    return AudioSound::BAD;
-  }
-}
-
-/**
- * Stops the sound from playing and releases any associated resources, in
- * preparation for releasing the sound or shutting down the sound system.
- */
-void MilesAudioSequence::
-cleanup() {
-  stop();
-}
-
-/**
- * Called by the GlobalMilesManager when it is detected that this particular
- * sound has already stopped, and its sequence handle will be recycled.
- */
-void MilesAudioSequence::
-internal_stop() {
-  _sequence = 0;
-  _sequence_index = 0;
-}
-
-/**
- * This callback is made by Miles (possibly in a sub-thread) when the sequence
- * finishes.
- */
-void AILCALLBACK MilesAudioSequence::
-finish_callback(HSEQUENCE sequence) {
-  MilesAudioSequence *self = (MilesAudioSequence *)AIL_sequence_user_data(sequence, 0);
-  if (milesAudio_cat.is_debug()) {
-    milesAudio_cat.debug()
-      << "finished " << *self << "\n";
-  }
-  self->_manager->_sounds_finished = true;
-}
-
-/**
- * Sets the start time of an already allocated stream.
- */
-void MilesAudioSequence::
-do_set_time(PN_stdfloat time) {
-  miles_audio_debug("do_set_time(time="<<time<<")");
-
-  nassertv(_sequence != 0);
-
-  S32 time_ms = (S32)(1000.0f * time);
-
-    // Ensure we don't inadvertently run off the end of the sound.
-  S32 length_ms;
-  AIL_sequence_ms_position(_sequence, &length_ms, nullptr);
-  time_ms = std::min(time_ms, length_ms);
-
-  AIL_set_sequence_ms_position(_sequence, time_ms);
-}
-
-
-/**
- * Temporarily loads the sequence to determine its length.  Stores the result
- * on the _sd.
- */
-void MilesAudioSequence::
-determine_length() {
-  nassertv(_sequence == 0);
-
-  GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
-  if (!mgr->get_sequence(_sequence, _sequence_index, this)){
-    milesAudio_cat.warning()
-      << "Could not determine length of " << _file_name << ": too many open sequences\n";
-    _sequence = 0;
-  } else {
-    AIL_init_sequence(_sequence, &_sd->_raw_data[0], 0);
-    S32 length_ms;
-    AIL_sequence_ms_position(_sequence, &length_ms, nullptr);
-    PN_stdfloat time = (PN_stdfloat)length_ms * 0.001f;
-    mgr->release_sequence(_sequence_index, this);
-    _sequence = 0;
-    _sequence_index = 0;
-
-    _sd->set_length(time);
-  }
-}
-
-#endif //]

+ 0 - 88
panda/src/audiotraits/milesAudioSequence.h

@@ -1,88 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file milesAudioSequence.h
- * @author drose
- * @date 2007-07-31
- */
-
-#ifndef MILESAUDIOSEQUENCE_H
-#define MILESAUDIOSEQUENCE_H
-
-#include "pandabase.h"
-#ifdef HAVE_RAD_MSS //[
-
-#include "milesAudioSound.h"
-#include "milesAudioManager.h"
-
-#include <mss.h>
-
-/**
- * A MIDI file, preloaded and played from a memory buffer.  MIDI files cannot
- * be streamed.
- */
-class EXPCL_MILES_AUDIO MilesAudioSequence : public MilesAudioSound {
-private:
-  MilesAudioSequence(MilesAudioManager *manager,
-                     MilesAudioManager::SoundData *sd,
-                     const std::string &file_name);
-
-public:
-  virtual ~MilesAudioSequence();
-
-  virtual void play();
-  virtual void stop();
-
-  virtual PN_stdfloat get_time() const;
-
-  virtual void set_volume(PN_stdfloat volume=1.0f);
-  virtual void set_balance(PN_stdfloat balance_right=0.0f);
-  virtual void set_play_rate(PN_stdfloat play_rate=1.0f);
-
-  virtual PN_stdfloat length() const;
-
-  virtual AudioSound::SoundStatus status() const;
-
-  virtual void cleanup();
-
-private:
-  void internal_stop();
-  static void AILCALLBACK finish_callback(HSEQUENCE sequence);
-  void do_set_time(PN_stdfloat time);
-  void determine_length();
-
-  PT(MilesAudioManager::SoundData) _sd;
-  HSEQUENCE _sequence;
-  size_t _sequence_index;
-
-public:
-  static TypeHandle get_class_type() {
-    return _type_handle;
-  }
-  static void init_type() {
-    MilesAudioSound::init_type();
-    register_type(_type_handle, "MilesAudioSequence",
-                  MilesAudioSound::get_class_type());
-  }
-  virtual TypeHandle get_type() const {
-    return get_class_type();
-  }
-  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
-
-private:
-  static TypeHandle _type_handle;
-
-  friend class GlobalMilesManager;
-  friend class MilesAudioManager;
-};
-
-#include "milesAudioSequence.I"
-
-#endif //]
-
-#endif  /* MILESAUDIOSEQUENCE_H */

+ 0 - 12
panda/src/audiotraits/milesAudioSound.I

@@ -1,12 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file milesAudioSound.I
- * @author drose
- * @date 2007-07-30
- */

+ 0 - 205
panda/src/audiotraits/milesAudioSound.cxx

@@ -1,205 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file milesAudioSound.cxx
- * @author drose
- * @date 2007-07-30
- */
-
-#include "milesAudioSound.h"
-#ifdef HAVE_RAD_MSS //[
-
-#include "milesAudioManager.h"
-
-using std::string;
-
-TypeHandle MilesAudioSound::_type_handle;
-
-#undef miles_audio_debug
-
-#ifndef NDEBUG //[
-#define miles_audio_debug(x) \
-    audio_debug("MilesAudioSound \""<<get_name()<<"\" "<< x )
-#else //][
-#define miles_audio_debug(x) ((void)0)
-#endif //]
-
-/**
- *
- */
-MilesAudioSound::
-MilesAudioSound(MilesAudioManager *manager,
-                const string &file_name) :
-  _manager(manager),
-  _file_name(file_name),
-  _volume(1.0f), _balance(0), _play_rate(1.0f),
-  _loop_count(1),
-  _active(true),
-  _paused(false),
-  _start_time(0.0f),
-  _got_start_time(false)
-{
-  nassertv(!file_name.empty());
-}
-
-/**
- *
- */
-void MilesAudioSound::
-set_loop(bool loop) {
-  // loop count of 0 means always loop
-  set_loop_count((loop)?0:1);
-}
-
-/**
- *
- */
-bool MilesAudioSound::
-get_loop() const {
-  return (_loop_count == 0);
-}
-
-/**
- *
- */
-void MilesAudioSound::
-set_loop_count(unsigned long loop_count) {
-  if (_loop_count != loop_count) {
-    _loop_count = loop_count;
-    if (status() == PLAYING) {
-      // hack: For now, the loop count is picked up when the sound starts
-      // playing.  There may be a way to change the loop count of a playing
-      // sound, but I'm going to focus on other things.  If you would like to
-      // change the need to stop and start the sound, feel free.  Or, maybe
-      // I'll spend time on it in the future.  Please set the loop option
-      // before starting the sound.
-      play();
-    }
-  }
-}
-
-/**
- *
- */
-unsigned long MilesAudioSound::
-get_loop_count() const {
-  return _loop_count;
-}
-
-/**
- *
- */
-PN_stdfloat MilesAudioSound::
-get_volume() const {
-  return _volume;
-}
-
-/**
- *
- */
-PN_stdfloat MilesAudioSound::
-get_balance() const {
-  return _balance;
-}
-
-/**
- *
- */
-PN_stdfloat MilesAudioSound::
-get_play_rate() const {
-  return _play_rate;
-}
-
-/**
- *
- */
-void MilesAudioSound::
-set_time(PN_stdfloat time) {
-  miles_audio_debug("set_time(time="<<time<<")");
-
-  // Mark this position for the next play().
-  _start_time = time;
-  _got_start_time = true;
-}
-
-/**
- *
- */
-void MilesAudioSound::
-set_active(bool active) {
-  if (_manager == nullptr) {
-    return;
-  }
-
-  miles_audio_debug("set_active(active="<<active<<")");
-  if (_active != active) {
-    _active = active;
-    if (_active) {
-      // ...activate the sound.
-      if (_paused && _loop_count==0) {
-        // ...this sound was looping when it was paused.
-        _paused = false;
-        play();
-      }
-
-    } else {
-      // ...deactivate the sound.
-      if (status() == PLAYING) {
-        if (_loop_count == 0) {
-          // ...we're pausing a looping sound.
-          _paused = true;
-        }
-        _start_time = get_time();
-        _got_start_time = true;
-        stop();
-      }
-    }
-  }
-}
-
-/**
- *
- */
-bool MilesAudioSound::
-get_active() const {
-  return _active;
-}
-
-/**
- * This is no longer implemented.
- */
-void MilesAudioSound::
-set_finished_event(const string &event) {
-  _finished_event = event;
-}
-
-/**
- * This is no longer implemented.
- */
-const string &MilesAudioSound::
-get_finished_event() const {
-  return _finished_event;
-}
-
-/**
- *
- */
-const string &MilesAudioSound::
-get_name() const {
-  return _file_name;
-}
-
-/**
- * Stops the sound from playing and releases any associated resources, in
- * preparation for releasing the sound or shutting down the sound system.
- */
-void MilesAudioSound::
-cleanup() {
-}
-
-#endif  //]

+ 0 - 107
panda/src/audiotraits/milesAudioSound.h

@@ -1,107 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file milesAudioSound.h
- * @author drose
- * @date 2007-07-30
- */
-
-#ifndef MILESAUDIOSOUND_H
-#define MILESAUDIOSOUND_H
-
-#include "pandabase.h"
-#ifdef HAVE_RAD_MSS //[
-
-#include "audioSound.h"
-#include "milesAudioManager.h"
-
-#include <mss.h>
-
-/**
- * The base class for both MilesAudioStream and MilesAudioSample.
- */
-class EXPCL_MILES_AUDIO MilesAudioSound : public AudioSound {
-protected:
-  MilesAudioSound(MilesAudioManager *manager, const std::string &file_name);
-
-public:
-  virtual void set_loop(bool loop=true);
-  virtual bool get_loop() const;
-
-  virtual void set_loop_count(unsigned long loop_count=1);
-  virtual unsigned long get_loop_count() const;
-
-  virtual PN_stdfloat get_volume() const;
-  virtual PN_stdfloat get_balance() const;
-  virtual PN_stdfloat get_play_rate() const;
-
-  virtual void set_time(PN_stdfloat start_time=0.0);
-
-  virtual void set_active(bool active=true);
-  virtual bool get_active() const;
-
-  virtual void set_finished_event(const std::string &event);
-  virtual const std::string &get_finished_event() const;
-
-  virtual const std::string &get_name() const;
-
-  virtual void cleanup();
-
-protected:
-  PT(MilesAudioManager) _manager;
-  std::string _file_name;
-
-  PN_stdfloat _volume; // 0..1.0
-  PN_stdfloat _balance; // -1..1
-  PN_stdfloat _play_rate; // 0..1.0
-  unsigned long _loop_count;
-
-  // _active is for things like a 'turn off sound effects' in a preferences
-  // pannel.  _active is not about whether a sound is currently playing.  Use
-  // status() for info on whether the sound is playing.
-  bool _active;
-
-  // _paused is not like the Pause button on a cddvd player.  It is used as a
-  // flag to say that the sound was looping when it was set inactive.
-  bool _paused;
-
-  // This is the string that throw_event() will throw when the sound finishes
-  // playing.  It is not triggered when the sound is stopped with stop().
-  // Note: no longer implemented.
-  std::string _finished_event;
-
-  // This is set whenever we call set_time().  Calling play() will respect
-  // this if it is set, and then reset it.
-  PN_stdfloat _start_time;
-  bool _got_start_time;
-
-public:
-  static TypeHandle get_class_type() {
-    return _type_handle;
-  }
-  static void init_type() {
-    AudioSound::init_type();
-    register_type(_type_handle, "MilesAudioSound",
-                  AudioSound::get_class_type());
-  }
-  virtual TypeHandle get_type() const {
-    return get_class_type();
-  }
-  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
-
-private:
-  static TypeHandle _type_handle;
-
-  friend class MilesAudioManager;
-};
-
-#include "milesAudioSound.I"
-
-#endif //]
-
-#endif

+ 0 - 12
panda/src/audiotraits/milesAudioStream.I

@@ -1,12 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file milesAudioStream.I
- * @author drose
- * @date 2007-07-26
- */

+ 0 - 310
panda/src/audiotraits/milesAudioStream.cxx

@@ -1,310 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file milesAudioStream.cxx
- * @author drose
- * @date 2007-07-26
- */
-
-#include "milesAudioStream.h"
-#ifdef HAVE_RAD_MSS //[
-
-#include "milesAudioManager.h"
-#include "pnotify.h"
-
-TypeHandle MilesAudioStream::_type_handle;
-
-#undef miles_audio_debug
-
-#ifndef NDEBUG //[
-#define miles_audio_debug(x) \
-    audio_debug("MilesAudioStream \""<<get_name()<<"\" "<< x )
-#else //][
-#define miles_audio_debug(x) ((void)0)
-#endif //]
-
-/**
- *
- */
-MilesAudioStream::
-MilesAudioStream(MilesAudioManager *manager, const std::string &file_name,
-                 const Filename &path) :
-  MilesAudioSound(manager, file_name),
-  _path(path)
-{
-  _stream = 0;
-  _got_length = false;
-}
-
-/**
- *
- */
-MilesAudioStream::
-~MilesAudioStream() {
-  miles_audio_debug("~MilesAudioStream()");
-  cleanup();
-
-  miles_audio_debug("~MilesAudioStream() done");
-}
-
-/**
- *
- */
-void MilesAudioStream::
-play() {
-  miles_audio_debug("play()");
-  if (_active) {
-
-    _manager->starting_sound(this);
-
-    if (_stream == 0) {
-      GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
-      _stream = AIL_open_stream(mgr->_digital_driver, _path.c_str(), 0);
-      if (_stream == 0) {
-        milesAudio_cat.warning()
-          << "Could not play " << _file_name << ": too many open streams\n";
-        return;
-      }
-      AIL_set_stream_user_data(_stream, 0, (SINTa)this);
-      AIL_register_stream_callback(_stream, finish_callback);
-
-    } else {
-      // We already had the stream open.  Keep it open; just restart it.
-      AIL_pause_stream(_stream, 1);
-      _manager->stop_service_stream(_stream);
-    }
-
-    // Start playing:
-    nassertv(_stream != 0);
-    HSAMPLE sample = AIL_stream_sample_handle(_stream);
-    nassertv(sample != 0);
-
-    _original_playback_rate = AIL_sample_playback_rate(sample);
-    set_volume(_volume);
-    set_play_rate(_play_rate);
-
-    AIL_set_stream_loop_count(_stream, _loop_count);
-
-    AIL_start_stream(_stream);
-    if (_got_start_time) {
-      // There's no AIL_resume_stream(), so we start in the middle by starting
-      // normally, then immediately skipping to the middle.
-      do_set_time(_start_time);
-    }
-
-    if (miles_audio_panda_threads) {
-      AIL_auto_service_stream(_stream, 0);
-      _manager->start_service_stream(_stream);
-    } else {
-      AIL_auto_service_stream(_stream, 1);
-    }
-
-    _got_start_time = false;
-
-  } else {
-    // In case _loop_count gets set to forever (zero):
-    audio_debug("  paused "<<_file_name );
-    _paused = true;
-  }
-}
-
-/**
- *
- */
-void MilesAudioStream::
-stop() {
-  if (_manager == nullptr) {
-    return;
-  }
-  miles_audio_debug("stop()");
-  _manager->stopping_sound(this);
-
-  // The _paused flag should not be cleared here.  _paused is not like the
-  // Pause button on a cddvd player.  It is used as a flag to say that it was
-  // looping when it was set inactive.  There is no need to make this
-  // symmetrical with play().  set_active() is the 'owner' of _paused.  play()
-  // accesses _paused to help in the situation where someone calls play on an
-  // inactive sound().
-  if (_stream != 0) {
-    _manager->stop_service_stream(_stream);
-
-    AIL_pause_stream(_stream, 1);
-    AIL_close_stream(_stream);
-    _stream = 0;
-  }
-}
-
-/**
- *
- */
-PN_stdfloat MilesAudioStream::
-get_time() const {
-  if (_stream == 0) {
-    if (_got_start_time) {
-      return _start_time;
-    }
-    return 0.0f;
-  }
-
-  S32 current_ms;
-  AIL_stream_ms_position(_stream, nullptr, &current_ms);
-  PN_stdfloat time = PN_stdfloat(current_ms * 0.001f);
-
-  return time;
-}
-
-/**
- *
- */
-void MilesAudioStream::
-set_volume(PN_stdfloat volume) {
-  _volume = volume;
-
-  if (_stream != 0) {
-    HSAMPLE sample = AIL_stream_sample_handle(_stream);
-    nassertv(sample != 0);
-
-    volume *= _manager->get_volume();
-
-    // Change to Miles volume, range 0 to 1.0:
-    F32 milesVolume = volume;
-    milesVolume = std::min(milesVolume, 1.0f);
-    milesVolume = std::max(milesVolume, 0.0f);
-
-    // Convert balance of -1.0..1.0 to 0-1.0:
-    F32 milesBalance = (F32)((_balance + 1.0f) * 0.5f);
-
-    AIL_set_sample_volume_pan(sample, milesVolume, milesBalance);
-  }
-}
-
-/**
- *
- */
-void MilesAudioStream::
-set_balance(PN_stdfloat balance_right) {
-  _balance = balance_right;
-
-  // Call set_volume to effect the change:
-  set_volume(_volume);
-}
-
-/**
- *
- */
-void MilesAudioStream::
-set_play_rate(PN_stdfloat play_rate) {
-  _play_rate = play_rate;
-
-  if (_stream != 0) {
-    HSAMPLE sample = AIL_stream_sample_handle(_stream);
-    nassertv(sample != 0);
-
-    play_rate *= _manager->get_play_rate();
-
-    // wave and mp3 use sample rate (e.g.  44100)
-    S32 speed = (S32)(play_rate * (PN_stdfloat)_original_playback_rate);
-    AIL_set_sample_playback_rate(sample, speed);
-    audio_debug("  play_rate for this wav or mp3 is now " << speed);
-  }
-}
-
-/**
- *
- */
-PN_stdfloat MilesAudioStream::
-length() const {
-  if (!_got_length) {
-    if (_stream == 0) {
-      GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
-      ((MilesAudioStream *)this)->_stream = AIL_open_stream(mgr->_digital_driver, _path.c_str(), 0);
-    }
-
-    S32 length_ms;
-    AIL_stream_ms_position(_stream, &length_ms, nullptr);
-    _length = (PN_stdfloat)length_ms * 0.001f;
-    _got_length = true;
-  }
-
-  return _length;
-}
-
-/**
- *
- */
-AudioSound::SoundStatus MilesAudioStream::
-status() const {
-  if (!_stream) {
-    return AudioSound::READY;
-  }
-
-  switch (AIL_stream_status(_stream)) {
-  case SMP_STOPPED:
-  case SMP_DONE:
-    return AudioSound::READY;
-  case SMP_PLAYING:
-  case SMP_PLAYINGBUTRELEASED:
-    return AudioSound::PLAYING;
-  default:
-    return AudioSound::BAD;
-  }
-}
-
-/**
- * Called to release any resources associated with the sound.
- */
-void MilesAudioStream::
-cleanup() {
-  if (_stream) {
-    stop();
-  }
-  set_active(false);
-  nassertv(_stream == 0);
-
-  if (_manager != nullptr) {
-    _manager->release_sound(this);
-    _manager = nullptr;
-  }
-}
-
-/**
- * This callback is made by Miles (possibly in a sub-thread) when the stream
- * finishes.
- */
-void AILCALLBACK MilesAudioStream::
-finish_callback(HSTREAM stream) {
-  MilesAudioStream *self = (MilesAudioStream *)AIL_stream_user_data(stream, 0);
-  if (milesAudio_cat.is_debug()) {
-    milesAudio_cat.debug()
-      << "finished " << *self << "\n";
-  }
-  if (self->_manager == nullptr) {
-    return;
-  }
-  self->_manager->_sounds_finished = true;
-}
-
-/**
- * Sets the start time of an already allocated stream.
- */
-void MilesAudioStream::
-do_set_time(PN_stdfloat time) {
-  nassertv(_stream != 0);
-
-  S32 time_ms = (S32)(1000.0f * time);
-
-  // Ensure we don't inadvertently run off the end of the sound.
-  S32 length_ms;
-  AIL_stream_ms_position(_stream, &length_ms, nullptr);
-  time_ms = std::min(time_ms, length_ms);
-
-  AIL_set_stream_ms_position(_stream, time_ms);
-}
-
-
-#endif //]

+ 0 - 87
panda/src/audiotraits/milesAudioStream.h

@@ -1,87 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file milesAudioStream.h
- * @author drose
- * @date 2007-07-26
- */
-
-#ifndef MILESAUDIOSTREAM_H
-#define MILESAUDIOSTREAM_H
-
-#include "pandabase.h"
-#ifdef HAVE_RAD_MSS //[
-
-#include "milesAudioSound.h"
-#include "milesAudioManager.h"
-
-#include <mss.h>
-
-/**
- * This represents a sound file played by the Miles Sound System, similar to
- * MilesAudioSample, except that it is streamed from disk instead of preloaded
- * into memory.
- */
-class EXPCL_MILES_AUDIO MilesAudioStream : public MilesAudioSound {
-private:
-  MilesAudioStream(MilesAudioManager *manager, const std::string &file_name,
-                   const Filename &path);
-
-public:
-  virtual ~MilesAudioStream();
-
-  virtual void play();
-  virtual void stop();
-
-  virtual PN_stdfloat get_time() const;
-
-  virtual void set_volume(PN_stdfloat volume=1.0f);
-  virtual void set_balance(PN_stdfloat balance_right=0.0f);
-  virtual void set_play_rate(PN_stdfloat play_rate=1.0f);
-
-  virtual PN_stdfloat length() const;
-
-  virtual AudioSound::SoundStatus status() const;
-
-  virtual void cleanup();
-
-private:
-  static void AILCALLBACK finish_callback(HSTREAM stream);
-  void do_set_time(PN_stdfloat time);
-
-  Filename _path;
-  HSTREAM _stream;
-  S32 _original_playback_rate;
-  mutable PN_stdfloat _length;
-  mutable bool _got_length;
-
-public:
-  static TypeHandle get_class_type() {
-    return _type_handle;
-  }
-  static void init_type() {
-    MilesAudioSound::init_type();
-    register_type(_type_handle, "MilesAudioStream",
-                  MilesAudioSound::get_class_type());
-  }
-  virtual TypeHandle get_type() const {
-    return get_class_type();
-  }
-  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
-
-private:
-  static TypeHandle _type_handle;
-
-  friend class MilesAudioManager;
-};
-
-#include "milesAudioStream.I"
-
-#endif //]
-
-#endif

+ 0 - 9
panda/src/audiotraits/miles_audio_composite1.cxx

@@ -1,9 +0,0 @@
-
-#include "config_milesAudio.cxx"
-#include "milesAudioManager.cxx"
-#include "milesAudioSample.cxx"
-#include "milesAudioSequence.cxx"
-#include "milesAudioSound.cxx"
-#include "milesAudioStream.cxx"
-#include "globalMilesManager.cxx"
-      

+ 1 - 1
panda/src/audiotraits/openalAudioManager.cxx

@@ -442,7 +442,7 @@ get_sound_data(MovieAudio *movie, int mode) {
     int channels = stream->audio_channels();
     int samples = (int)(stream->length() * stream->audio_rate());
     int16_t *data = new int16_t[samples * channels];
-    stream->read_samples(samples, data);
+    samples = stream->read_samples(samples, data);
     alBufferData(sd->_sample,
                  (channels>1) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16,
                  data, samples * channels * 2, stream->audio_rate());

Some files were not shown because too many files changed in this diff