소스 검색

Merge branch 'master' into shaderpipeline

rdb 6 년 전
부모
커밋
afd7525963
100개의 변경된 파일1189개의 추가작업 그리고 5069개의 파일을 삭제
  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/
 /targetroot/
 /dstroot/
 /dstroot/
 
 
-# Core dumps
+# Core dumps and traces
 core
 core
 core.*
 core.*
 vgcore.*
 vgcore.*
 *.core
 *.core
+*.trace
 
 
 # Editor files/directories
 # Editor files/directories
 *.save
 *.save
@@ -26,6 +27,7 @@ vgcore.*
 /+DESC
 /+DESC
 /+MANIFEST
 /+MANIFEST
 /pkg-plist
 /pkg-plist
+/debug.ks
 
 
 # Produced installer/executables
 # Produced installer/executables
 /*.exe
 /*.exe
@@ -36,6 +38,7 @@ vgcore.*
 /*.dmg
 /*.dmg
 /*.whl
 /*.whl
 /*.txz
 /*.txz
+/*.apk
 
 
 # CMake
 # CMake
 /build/
 /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)
 [![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"/>
 <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
 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
 If you are familiar with installing Python packages, you can use
 the following comand:
 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
 [click here](https://github.com/rdb/panda3d-thirdparty) for instructions on
 building them from source.
 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
 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
 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
 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,
 After placing the thirdparty directory inside the panda3d source directory,
 you may build Panda3D using a command like the following:
 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:
 Then, you can build and install the .apk right away using these commands:
 
 
 ```bash
 ```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
 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
 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.
 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 "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::cout;
 using std::endl;
 using std::endl;
 using std::string;
 using std::string;

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

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

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

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

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

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

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

@@ -13,6 +13,8 @@
 
 
 #include "pathFind.h"
 #include "pathFind.h"
 
 
+#include "pathFollow.h"
+
 using std::cout;
 using std::cout;
 using std::endl;
 using std::endl;
 using std::string;
 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 "pathFollow.h"
 
 
+#include "pathFind.h"
+
 PathFollow::PathFollow(AICharacter *ai_ch, float follow_wt) {
 PathFollow::PathFollow(AICharacter *ai_ch, float follow_wt) {
     _follow_weight = follow_wt;
     _follow_weight = follow_wt;
   _curr_path_waypoint = -1;
   _curr_path_waypoint = -1;

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

@@ -28,7 +28,7 @@
 #define SHADOWATLAS_H
 #define SHADOWATLAS_H
 
 
 #include "pandabase.h"
 #include "pandabase.h"
-#include "lvecBase4.h"
+#include "luse.h"
 
 
 NotifyCategoryDecl(shadowatlas, EXPORT_CLASS, EXPORT_TEMPL);
 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.isAirborne = 0
         self.highMark = 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):
     def setWalkSpeed(self, forward, jump, reverse, rotate):
         assert self.notify.debugStateCall(self)
         assert self.notify.debugStateCall(self)
         self.avatarControlForwardSpeed=forward
         self.avatarControlForwardSpeed=forward

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

@@ -67,51 +67,6 @@ class PhysicsWalker(DirectObject.DirectObject):
         self.isAirborne = 0
         self.isAirborne = 0
         self.highMark = 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):
     def setWalkSpeed(self, forward, jump, reverse, rotate):
         assert self.debugPrint("setWalkSpeed()")
         assert self.debugPrint("setWalkSpeed()")
         self.avatarControlForwardSpeed=forward
         self.avatarControlForwardSpeed=forward

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

@@ -13,6 +13,7 @@ import stat
 import struct
 import struct
 import imp
 import imp
 import string
 import string
+import time
 
 
 import setuptools
 import setuptools
 import distutils.log
 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.
     # Python 3 defines these subtypes of IOError, but Python 2 doesn't.
     FileNotFoundError = IOError
     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):
 def _parse_list(input):
     if isinstance(input, basestring):
     if isinstance(input, basestring):
@@ -229,7 +239,9 @@ class build_apps(setuptools.Command):
         self.requirements_path = os.path.join(os.getcwd(), 'requirements.txt')
         self.requirements_path = os.path.join(os.getcwd(), 'requirements.txt')
         self.use_optimized_wheels = True
         self.use_optimized_wheels = True
         self.optimized_wheel_index = ''
         self.optimized_wheel_index = ''
-        self.pypi_extra_indexes = []
+        self.pypi_extra_indexes = [
+            'https://archive.panda3d.org/thirdparty',
+        ]
         self.file_handlers = {}
         self.file_handlers = {}
         self.exclude_dependencies = [
         self.exclude_dependencies = [
             # Windows
             # Windows

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

@@ -124,7 +124,7 @@ class FilterManager(DirectObject):
 
 
         return winx,winy
         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
         """ Causes the scene to be rendered into the supplied textures
         instead of into the original window.  Puts a fullscreen quad
         instead of into the original window.  Puts a fullscreen quad
@@ -185,7 +185,10 @@ class FilterManager(DirectObject):
         # Choose the size of the offscreen buffer.
         # Choose the size of the offscreen buffer.
 
 
         (winx, winy) = self.getScaledSize(1,1,1)
         (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):
         if (buffer == None):
             return None
             return None
@@ -236,7 +239,7 @@ class FilterManager(DirectObject):
 
 
         return quad
         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
         """ Creates an offscreen buffer for an intermediate
         computation. Installs a quad into the buffer.  Returns
         computation. Installs a quad into the buffer.  Returns
@@ -250,7 +253,10 @@ class FilterManager(DirectObject):
 
 
         depthbits = bool(depthtex != None)
         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):
         if (buffer == None):
             return None
             return None
@@ -287,7 +293,7 @@ class FilterManager(DirectObject):
 
 
         return quad
         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. """
         """ Low-level buffer creation.  Not intended for public use. """
 
 
         winprops = WindowProperties()
         winprops = WindowProperties()
@@ -297,6 +303,9 @@ class FilterManager(DirectObject):
         props.setRgbColor(1)
         props.setRgbColor(1)
         props.setDepthBits(depthbits)
         props.setDepthBits(depthbits)
         props.setStereo(self.win.isStereo())
         props.setStereo(self.win.isStereo())
+        if fbprops is not None:
+            props.addProperties(fbprops)
+
         depthtex, colortex, auxtex0, auxtex1 = texgroup
         depthtex, colortex, auxtex0, auxtex1 = texgroup
         if (auxtex0 != None):
         if (auxtex0 != None):
             props.setAuxRgba(1)
             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
             # List of items to display on the popup menu
             ('items',       [],             self.setItems),
             ('items',       [],             self.setItems),
             # Initial item to display on menu button
             # 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),
             ('initialitem', None,           DGG.INITOPT),
             # Amount of padding to place around popup button indicator
             # Amount of padding to place around popup button indicator
             ('popupMarkerBorder', (.1, .1), None),
             ('popupMarkerBorder', (.1, .1), None),
+            # The initial position of the popup marker
+            ('popupMarker_pos', None, None),
             # Background color to use to highlight popup menu items
             # Background color to use to highlight popup menu items
             ('highlightColor', (.5, .5, .5, 1), None),
             ('highlightColor', (.5, .5, .5, 1), None),
             # Extra scale to use on highlight popup menu items
             # 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),
             frameSize = (-0.5, 0.5, -0.2, 0.2),
             scale = 0.4,
             scale = 0.4,
             relief = DGG.RAISED)
             relief = DGG.RAISED)
+        # Record any user specified popup marker position
+        self.initPopupMarkerPos = self['popupMarker_pos']
         # This needs to popup the menu too
         # This needs to popup the menu too
         self.popupMarker.bind(DGG.B1PRESS, self.showPopupMenu)
         self.popupMarker.bind(DGG.B1PRESS, self.showPopupMenu)
         # Check if item is highlighted on release and select it if it is
         # Check if item is highlighted on release and select it if it is
@@ -168,8 +172,13 @@ class DirectOptionMenu(DirectButton):
         else:
         else:
             # Or base it upon largest item
             # Or base it upon largest item
             bounds = [self.minX, self.maxX, self.minZ, self.maxZ]
             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
         # Adjust popup menu button to fit all items (or use user specified
         # frame size
         # frame size
         bounds[1] += pmw
         bounds[1] += pmw
@@ -184,6 +193,12 @@ class DirectOptionMenu(DirectButton):
         Adjust popup position if default position puts it outside of
         Adjust popup position if default position puts it outside of
         visible screen region
         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
         # Show the menu
         self.popupMenu.show()
         self.popupMenu.show()
         # Make sure its at the right scale
         # 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])
                 simpleChildGui = self.guiDict.get(parts[-1])
                 if simpleChildGui:
                 if simpleChildGui:
                     simpleChildGui.destroy()
                     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)
         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
     # than explicitly restarting the sound every time around. This
     # prevents a skip in the sound at every repetition (the gap in
     # 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
     # 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
     # RAU 03/01/07 add listenerNode in case we don't want to
     # use base.camera as the listener, node must not be None
     # use base.camera as the listener, node must not be None
     def __init__(self, sound, loop = 0, duration = 0.0, name = None,
     def __init__(self, sound, loop = 0, duration = 0.0, name = None,
@@ -62,23 +61,6 @@ class SoundInterval(Interval.Interval):
             #if (duration == 0):
             #if (duration == 0):
             #    self.notify.warning('zero length duration!')
             #    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
         # Generate unique name if necessary
         if (name == None):
         if (name == None):

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

@@ -442,3 +442,21 @@ class BufferViewer(DirectObject):
                     cards[index] = placer
                     cards[index] = placer
 
 
         return Task.cont
         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()):
             for key in list(acceptorDict.keys()):
                 function, extraArgs, persistent = acceptorDict[key]
                 function, extraArgs, persistent = acceptorDict[key]
                 object = self._getObject(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:
                 else:
                     className = "Not a class"
                     className = "Not a class"
                 functionName = function.__name__
                 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
     """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. rng must return 0..1. if you happen to have the sum of the
     weights, pass it in 'sum'."""
     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
     # TODO: add support for dicts
     if sum is None:
     if sum is None:
         sum = 0.
         sum = 0.
@@ -1138,6 +1142,7 @@ def weightedChoice(choiceList, rng=random.random, sum=None):
 
 
     rand = rng()
     rand = rng()
     accum = rand * sum
     accum = rand * sum
+    item = None
     for weight, item in choiceList:
     for weight, item in choiceList:
         accum -= weight
         accum -= weight
         if accum <= 0.:
         if accum <= 0.:
@@ -1652,17 +1657,15 @@ def itype(obj):
     # version of type that gives more complete information about instance types
     # version of type that gives more complete information about instance types
     global dtoolSuperBase
     global dtoolSuperBase
     t = type(obj)
     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:
     else:
         # C++ object instances appear to be types via type()
         # C++ object instances appear to be types via type()
         # check if this is a C++ object
         # check if this is a C++ object
         if dtoolSuperBase is None:
         if dtoolSuperBase is None:
             _getDtoolSuperBase()
             _getDtoolSuperBase()
         if isinstance(obj, dtoolSuperBase):
         if isinstance(obj, dtoolSuperBase):
-            return '%s of %s>' % (repr(types.InstanceType)[:-1],
-                                  str(obj.__class__))
+            return "<type 'instance' of %s>" % (obj.__class__)
         return t
         return t
 
 
 def deeptype(obj, maxLen=100, _visitedIds=None):
 def deeptype(obj, maxLen=100, _visitedIds=None):

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

@@ -53,6 +53,8 @@ class SfxPlayer:
                 d = node.getDistance(listenerNode)
                 d = node.getDistance(listenerNode)
             else:
             else:
                 d = node.getDistance(base.cam)
                 d = node.getDistance(base.cam)
+        if not cutoff:
+            cutoff = self.cutoffDistance
         if d == None or d > cutoff:
         if d == None or d > cutoff:
             volume = 0
             volume = 0
         else:
         else:
@@ -70,9 +72,6 @@ class SfxPlayer:
             self, sfx, looping = 0, interrupt = 1, volume = None,
             self, sfx, looping = 0, interrupt = 1, volume = None,
             time = 0.0, node=None, listenerNode = None, cutoff = None):
             time = 0.0, node=None, listenerNode = None, cutoff = None):
         if sfx:
         if sfx:
-            if not cutoff:
-                cutoff = self.cutoffDistance
-
             self.setFinalVolume(sfx, node, volume, listenerNode, cutoff)
             self.setFinalVolume(sfx, node, volume, listenerNode, cutoff)
 
 
             # don't start over if it's already playing, unless
             # 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)
             win.requestProperties(props)
 
 
         mainWindow = False
         mainWindow = False
-        if self.win == None:
+        if self.win is None:
             mainWindow = True
             mainWindow = True
             self.win = win
             self.win = win
+            if hasattr(self, 'bufferViewer'):
+                self.bufferViewer.win = win
 
 
         self.winList.append(win)
         self.winList.append(win)
 
 
@@ -1677,13 +1679,19 @@ class ShowBase(DirectObject.DirectObject):
         return self.mouseWatcherNode.getModifierButtons().isDown(
         return self.mouseWatcherNode.getModifierButtons().isDown(
             KeyboardButton.meta())
             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
         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
         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
         given and not None, it is used to prefix events generated by this
         device, separated by a hyphen.
         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
         If you call this, you should consider calling detachInputDevice when
         you are done with the device or when it is disconnected.
         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))
         idn = self.dataRoot.attachNewNode(InputDeviceNode(device, device.name))
 
 
         # Setup the button thrower to generate events for the device.
         # 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))
         assert self.notify.debug("Attached input device {0} with prefix {1}".format(device, prefix))
         self.__inputDeviceNodes[device] = idn
         self.__inputDeviceNodes[device] = idn
-        self.deviceButtonThrowers.append(bt)
+
+        if watch:
+            idn.node().addChild(self.mouseWatcherNode)
 
 
     def detachInputDevice(self, device):
     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.
             # Look for a single rectangular hole to hold this piece.
             tp = self.findHole(tr.area, tr.w, tr.h)
             tp = self.findHole(tr.area, tr.w, tr.h)
             if tp:
             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:
                 if texCmp != 0 and holeCmp != 0 and texCmp != holeCmp:
                     tp.rotated = True
                     tp.rotated = True
                 tr.placements = [tp]
                 tr.placements = [tp]
@@ -803,10 +804,11 @@ class TexMemWatcher(DirectObject):
             # in.
             # in.
             tpList = self.findHolePieces(tr.area)
             tpList = self.findHolePieces(tr.area)
             if tpList:
             if tpList:
-                texCmp = cmp(tr.w, tr.h)
+                texCmp = (tr.w > tr.h) - (tr.w < tr.h)
                 tr.placements = tpList
                 tr.placements = tpList
                 for tp in 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:
                     if texCmp != 0 and holeCmp != 0 and texCmp != holeCmp:
                         tp.rotated = True
                         tp.rotated = True
                     tp.setBitmasks(self.bitmasks)
                     tp.setBitmasks(self.bitmasks)
@@ -858,11 +860,11 @@ class TexMemWatcher(DirectObject):
             # we have to squish it?
             # we have to squish it?
             if tw < w:
             if tw < w:
                 # We'd have to make it taller.
                 # We'd have to make it taller.
-                nh = min(area / tw, th)
+                nh = min(area // tw, th)
                 th = nh
                 th = nh
             elif th < h:
             elif th < h:
                 # We'd have to make it narrower.
                 # We'd have to make it narrower.
-                nw = min(area / th, tw)
+                nw = min(area // th, tw)
                 tw = nw
                 tw = nw
             else:
             else:
                 # Hey, we don't have to squish it after all!  Just
                 # Hey, we don't have to squish it after all!  Just
@@ -912,7 +914,7 @@ class TexMemWatcher(DirectObject):
             tpArea = (r - l) * (t - b)
             tpArea = (r - l) * (t - b)
             if tpArea >= area:
             if tpArea >= area:
                 # we're done.
                 # we're done.
-                shorten = (tpArea - area) / (r - l)
+                shorten = (tpArea - area) // (r - l)
                 t -= shorten
                 t -= shorten
                 tp.p = (l, r, b, t)
                 tp.p = (l, r, b, t)
                 tp.area = (r - l) * (t - b)
                 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"):
     def __init__(self, name = "PythonLock"):
         core.Mutex.__init__(self, name)
         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):
 class RLock(core.ReMutex):
     """ This class provides a wrapper around Panda's ReMutex object.
     """ This class provides a wrapper around Panda's ReMutex object.
@@ -221,18 +210,6 @@ class RLock(core.ReMutex):
     def __init__(self, name = "PythonRLock"):
     def __init__(self, name = "PythonRLock"):
         core.ReMutex.__init__(self, name)
         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):
 class Condition(core.ConditionVarFull):
     """ This class provides a wrapper around Panda's 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):
     def __setupTask(self, funcOrTask, name, priority, sort, extraArgs, taskChain, appendTask, owner, uponDeath):
         if isinstance(funcOrTask, AsyncTask):
         if isinstance(funcOrTask, AsyncTask):
             task = funcOrTask
             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)
             task = PythonTask(funcOrTask)
             if name is None:
             if name is None:
                 name = getattr(funcOrTask, '__qualname__', None) or \
                 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.
 # Import Tkinter, Pmw, and the floater code from this directory tree.
 from direct.tkwidgets.AppShell import *
 from direct.tkwidgets.AppShell import *
 from direct.showbase.TkGlobal import *
 from direct.showbase.TkGlobal import *
-import Pmw, sys
+import Pmw, sys, os
 from direct.task import Task
 from direct.task import Task
+from panda3d.core import Filename, getModelPath
 
 
 if sys.version_info >= (3, 0):
 if sys.version_info >= (3, 0):
     from tkinter.simpledialog import askfloat
     from tkinter.simpledialog import askfloat
+    from tkinter.filedialog import askopenfilename
 else:
 else:
     from tkSimpleDialog import askfloat
     from tkSimpleDialog import askfloat
+    from tkFileDialog import askopenfilename
 
 
 
 
 FRAMES = 0
 FRAMES = 0
@@ -273,7 +276,7 @@ class AnimPanel(AppShell):
             title = 'Load Animation',
             title = 'Load Animation',
             parent = self.component('hull')
             parent = self.component('hull')
             )
             )
-        if (animFilename == ''):
+        if not animFilename:
             # no file selected, canceled
             # no file selected, canceled
             return
             return
 
 
@@ -369,8 +372,9 @@ class AnimPanel(AppShell):
     def destroy(self):
     def destroy(self):
         # First clean up
         # First clean up
         taskMgr.remove(self.id + '_UpdateTask')
         taskMgr.remove(self.id + '_UpdateTask')
-        self.destroyCallBack()
-        self.destroyCallBack = None
+        if self.destroyCallBack is not None:
+            self.destroyCallBack()
+            self.destroyCallBack = None
         AppShell.destroy(self)
         AppShell.destroy(self)
 
 
 class ActorControl(Pmw.MegaWidget):
 class ActorControl(Pmw.MegaWidget):

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

@@ -96,22 +96,21 @@ class ParticlePanel(AppShell):
 
 
         ## MENUBAR ENTRIES ##
         ## MENUBAR ENTRIES ##
         # FILE MENU
         # 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
         # PARTICLE MANAGER MENU
         self.menuBar.addmenu('ParticleMgr', 'ParticleMgr Operations')
         self.menuBar.addmenu('ParticleMgr', 'ParticleMgr Operations')
@@ -215,23 +214,23 @@ class ParticlePanel(AppShell):
             ('System', 'Pool Size',
             ('System', 'Pool Size',
              'Max number of simultaneous particles',
              'Max number of simultaneous particles',
              self.setSystemPoolSize,
              self.setSystemPoolSize,
-             1.0, 1.0),
+             1.0, 2000000, 1.0),
             ('System', 'Birth Rate',
             ('System', 'Birth Rate',
              'Seconds between particle births',
              'Seconds between particle births',
              self.setSystemBirthRate,
              self.setSystemBirthRate,
-             0.0, None),
+             0.0, None, None),
             ('System', 'Litter Size',
             ('System', 'Litter Size',
              'Number of particle created at each birth',
              'Number of particle created at each birth',
              self.setSystemLitterSize,
              self.setSystemLitterSize,
-             1.0, 1.0),
+             1.0, 0x7fffffff, 1.0),
             ('System', 'Litter Spread',
             ('System', 'Litter Spread',
              'Variation in litter size',
              'Variation in litter size',
              self.setSystemLitterSpread,
              self.setSystemLitterSpread,
-             0.0, 1.0),
+             0.0, 0x7fffffff, 1.0),
             ('System', 'Lifespan',
             ('System', 'Lifespan',
              'Age in seconds at which the system (vs. particles) should die',
              'Age in seconds at which the system (vs. particles) should die',
              self.setSystemLifespan,
              self.setSystemLifespan,
-             0.0, None)
+             0.0, None, None)
             )
             )
         self.createFloaters(systemPage, systemFloaterDefs)
         self.createFloaters(systemPage, systemFloaterDefs)
 
 
@@ -270,27 +269,27 @@ class ParticlePanel(AppShell):
             ('Factory', 'Life Span',
             ('Factory', 'Life Span',
              'Average particle lifespan in seconds',
              'Average particle lifespan in seconds',
              self.setFactoryLifeSpan,
              self.setFactoryLifeSpan,
-             0.0, None),
+             0.0, None, None),
             ('Factory', 'Life Span Spread',
             ('Factory', 'Life Span Spread',
              'Variation in lifespan',
              'Variation in lifespan',
              self.setFactoryLifeSpanSpread,
              self.setFactoryLifeSpanSpread,
-             0.0, None),
+             0.0, None, None),
             ('Factory', 'Mass',
             ('Factory', 'Mass',
              'Average particle mass',
              'Average particle mass',
              self.setFactoryParticleMass,
              self.setFactoryParticleMass,
-             0.001, None),
+             0.001, None, None),
             ('Factory', 'Mass Spread',
             ('Factory', 'Mass Spread',
              'Variation in particle mass',
              'Variation in particle mass',
              self.setFactoryParticleMassSpread,
              self.setFactoryParticleMassSpread,
-             0.0, None),
+             0.0, None, None),
             ('Factory', 'Terminal Velocity',
             ('Factory', 'Terminal Velocity',
              'Cap on average particle velocity',
              'Cap on average particle velocity',
              self.setFactoryTerminalVelocity,
              self.setFactoryTerminalVelocity,
-             0.0, None),
+             0.0, None, None),
             ('Factory', 'Terminal Vel. Spread',
             ('Factory', 'Terminal Vel. Spread',
              'Variation in terminal velocity',
              'Variation in terminal velocity',
              self.setFactoryTerminalVelocitySpread,
              self.setFactoryTerminalVelocitySpread,
-             0.0, None),
+             0.0, None, None),
         )
         )
         self.createFloaters(factoryPage, factoryWidgets)
         self.createFloaters(factoryPage, factoryWidgets)
 
 
@@ -967,19 +966,29 @@ class ParticlePanel(AppShell):
 
 
     def createFloaters(self, parent, widgetDefinitions):
     def createFloaters(self, parent, widgetDefinitions):
         widgets = []
         widgets = []
-        for category, label, balloonHelp, command, min, resolution in widgetDefinitions:
+        for category, label, balloonHelp, command, min, max, resolution in widgetDefinitions:
             widgets.append(
             widgets.append(
                 self.createFloater(parent, category, label, balloonHelp,
                 self.createFloater(parent, category, label, balloonHelp,
-                                   command, min, resolution)
+                                   command, min, max, resolution)
                 )
                 )
         return widgets
         return widgets
 
 
     def createFloater(self, parent, category, text, balloonHelp,
     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['text'] = text
         kw['min'] = min
         kw['min'] = min
+        if max is not None:
+            kw['max'] = max
         kw['resolution'] = resolution
         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
         kw['numDigits'] = numDigits
         widget = Floater.Floater(parent, **kw)
         widget = Floater.Floater(parent, **kw)
         # Do this after the widget so command isn't called on creation
         # 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)
     pButton.pack(expand = 1, fill = BOTH)
 
 
     # Update menu
     # Update menu
-    menu = vgp.component('menubar').component('Valuator Group-menu')
+    menubar = vgp.component('menubar')
+    menubar.deletemenuitems('Valuator Group', 1, 1)
+
     # Some helper functions
     # Some helper functions
     # Clear color
     # 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
     # 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
     # 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):
     def setNodePathColor(color):
         nodePath.setColor(color[0]/255.0, color[1]/255.0,
         nodePath.setColor(color[0]/255.0, color[1]/255.0,
@@ -724,18 +734,23 @@ def lightRGBPanel(light, style = 'mini'):
     # Update menu button
     # Update menu button
     vgp.component('menubar').component('Valuator Group-button')['text'] = (
     vgp.component('menubar').component('Valuator Group-button')['text'] = (
         'Light Control Panel')
         'Light Control Panel')
+
     # Add a print button which will also serve as a color tile
     # Add a print button which will also serve as a color tile
     pButton = Button(vgp.interior(), text = 'Print to Log',
     pButton = Button(vgp.interior(), text = 'Print to Log',
                      bg = getTkColorString(initColor),
                      bg = getTkColorString(initColor),
                      command = printToLog)
                      command = printToLog)
     pButton.pack(expand = 1, fill = BOTH)
     pButton.pack(expand = 1, fill = BOTH)
+
     # Update menu
     # Update menu
-    menu = vgp.component('menubar').component('Valuator Group-menu')
+    menubar = vgp.component('menubar')
     # System color picker
     # 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):
     def setLightColor(color):
         light.setColor(Vec4(color[0]/255.0, color[1]/255.0,
         light.setColor(Vec4(color[0]/255.0, color[1]/255.0,
                             color[2]/255.0, color[3]/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  -----------------------
 ------------------------  RELEASE 1.10.1  -----------------------
 
 
 This is a bugfix release intended to fix several issues in 1.10.0.
 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::
 INLINE bool MutexWin32Impl::
 try_lock() {
 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;
 extern int GLOBAL_ARGC;
 #endif
 #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
 // 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
 // safely access them at stat init time--at least, not in libc5. (It does seem
 // to work with glibc2, however.)
 // 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
   // First, we need to fill in _dtool_name.  This contains the full path to
   // the p3dtool library.
   // 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;
     static const DWORD buffer_size = 1024;
     wchar_t buffer[buffer_size];
     wchar_t buffer[buffer_size];
     DWORD size = GetModuleFileNameW(dllhandle, buffer, buffer_size);
     DWORD size = GetModuleFileNameW(dllhandle, buffer, buffer_size);
@@ -562,46 +601,44 @@ read_args() {
       _dtool_name = tmp;
       _dtool_name = tmp;
     }
     }
   }
   }
-#endif
 
 
-#if defined(__APPLE__)
+#elif defined(__APPLE__)
   // And on OSX we don't have procselfmaps, but some _dyld_* functions.
   // 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;
         _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.
   // When building with glibc/uClibc, we typically have access to RTLD_DI_ORIGIN in Unix-like operating systems.
 
 
   char origin[PATH_MAX + 1];
   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) {
     if (dtool_handle != nullptr && dlinfo(dtool_handle, RTLD_DI_ORIGIN, origin) != -1) {
       _dtool_name = origin;
       _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.
   // 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()) {
   if (_dtool_name.empty()) {
     struct link_map *map;
     struct link_map *map;
@@ -610,16 +647,24 @@ read_args() {
 #else
 #else
     void *self = dlopen(NULL, RTLD_NOW | RTLD_NOLOAD);
     void *self = dlopen(NULL, RTLD_NOW | RTLD_NOLOAD);
 #endif
 #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
 #endif
@@ -634,19 +679,27 @@ read_args() {
     pifstream maps("/proc/self/maps");
     pifstream maps("/proc/self/maps");
 #endif
 #endif
     while (!maps.fail() && !maps.eof()) {
     while (!maps.fail() && !maps.eof()) {
+      if (!_dtool_name.empty()) break;
+
       char buffer[PATH_MAX];
       char buffer[PATH_MAX];
       buffer[0] = 0;
       buffer[0] = 0;
       maps.getline(buffer, PATH_MAX);
       maps.getline(buffer, PATH_MAX);
-      const char *tail = strrchr(buffer, '/');
       const char *head = strchr(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();
     maps.close();
   }
   }
 #endif
 #endif
+#endif /* !LINK_ALL_STATIC */
 
 
   // Now, we need to fill in _binary_name.  This contains the full path to the
   // Now, we need to fill in _binary_name.  This contains the full path to the
   // currently running executable.
   // 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 "filename_ext.cxx"
 #include "globPattern_ext.cxx"
 #include "globPattern_ext.cxx"
+#include "iostream_ext.cxx"
 #include "textEncoder_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.
     // 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) {
     if (array_type != nullptr) {
       call << "std::copy(" << expr << ", " << expr << " + " << *array_type->_bounds << ", ";
       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 << " = ";
       call << expr << " = ";
     }
     }
 
 
     _parameters[_first_true_parameter]._remap->pass_parameter(call,
     _parameters[_first_true_parameter]._remap->pass_parameter(call,
                     get_parameter_expr(_first_true_parameter, pexprs));
                     get_parameter_expr(_first_true_parameter, pexprs));
 
 
-    if (array_type != nullptr) {
+    if (paren_close) {
       call << ')';
       call << ')';
     }
     }
 
 
@@ -772,6 +780,11 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
     _return_value_destructor = builder.get_destructor_for(return_meat_type);
     _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.
   // Check for a special meaning by name and signature.
   size_t first_param = 0;
   size_t first_param = 0;
   if (_has_this) {
   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;
     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__") {
   if (method_name == "__ipow__") {
     def._answer_location = "nb_inplace_power";
     def._answer_location = "nb_inplace_power";
     def._wrapper_type = WT_inplace_ternary_operator;
     def._wrapper_type = WT_inplace_ternary_operator;
@@ -1690,7 +1696,6 @@ write_module_class(ostream &out, Object *obj) {
             SlottedFunctionDef def;
             SlottedFunctionDef def;
             def._answer_location = true_key;
             def._answer_location = true_key;
             def._wrapper_type = slotted_def._wrapper_type;
             def._wrapper_type = slotted_def._wrapper_type;
-            def._min_version = 0x03000000;
             def._wrapper_name = func->_name + "_" + true_key;
             def._wrapper_name = func->_name + "_" + true_key;
             slots[true_key] = def;
             slots[true_key] = def;
           }
           }
@@ -1886,7 +1891,9 @@ write_module_class(ostream &out, Object *obj) {
             out << "    Py_INCREF(Py_NotImplemented);\n";
             out << "    Py_INCREF(Py_NotImplemented);\n";
             out << "    return Py_NotImplemented;\n";
             out << "    return Py_NotImplemented;\n";
           } else if (all_nonconst) {
           } 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";
             out << "    return nullptr;\n";
           } else {
           } else {
             out << "  if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n";
             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";
       expected_params += "NoneType";
 
 
     } else if (TypeManager::is_char(type)) {
     } 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";
       expected_params += "char";
       only_pyobjects = false;
       only_pyobjects = false;
 
 
@@ -5993,7 +6001,11 @@ write_function_instance(ostream &out, FunctionRemap *remap,
       indent(out, indent_level) << "}\n";
       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);
     return_expr = remap->_return_type->temporary_to_return(return_expr);
   }
   }
 
 

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

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

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

@@ -574,6 +574,8 @@ main(int argc, char **argv) {
     the_output_include = &output_include;
     the_output_include = &output_include;
   }
   }
 
 
+  int status = 0;
+
   // Now output all of the wrapper functions.
   // Now output all of the wrapper functions.
   if (!output_code_filename.empty())
   if (!output_code_filename.empty())
   {
   {
@@ -595,6 +597,7 @@ main(int argc, char **argv) {
 
 
     if (output_code.fail()) {
     if (output_code.fail()) {
       nout << "Unable to write to " << output_code_filename << "\n";
       nout << "Unable to write to " << output_code_filename << "\n";
+      status = -1;
     } else {
     } else {
       builder.write_code(output_code,the_output_include, def);
       builder.write_code(output_code,the_output_include, def);
     }
     }
@@ -609,13 +612,13 @@ main(int argc, char **argv) {
     pofstream output_data;
     pofstream output_data;
     output_data_filename.open_write(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";
       nout << "Unable to write to " << output_data_filename << "\n";
+      status = -1;
     } else {
     } else {
       InterrogateDatabase::get_ptr()->write(output_data, def);
       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);
   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.
  * 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)
 #define Dtool_Return(value) _Dtool_Return(value)
 #endif
 #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.
  * 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;
   Dtool_WrapperBase *wrap = (Dtool_WrapperBase *)self;
   nassertv(wrap);
   nassertv(wrap);
   Py_XDECREF(wrap->_self);
   Py_XDECREF(wrap->_self);
+  Py_TYPE(self)->tp_free(self);
 }
 }
 
 
 static PyObject *Dtool_WrapperBase_repr(PyObject *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
 // This file, and all the other files in this directory, aren't
 // intended to be compiled--they're just parsed by CPPParser (and
 // intended to be compiled--they're just parsed by CPPParser (and
@@ -34,6 +33,9 @@ namespace std {
   __published:
   __published:
     ostream(const ostream&) = delete;
     ostream(const ostream&) = delete;
 
 
+    __extension void write(PyObject *b);
+    __extension void writelines(PyObject *lines);
+
     void put(char c);
     void put(char c);
     void flush();
     void flush();
     streampos tellp();
     streampos tellp();
@@ -43,10 +45,20 @@ namespace std {
   protected:
   protected:
     ostream(ostream &&);
     ostream(ostream &&);
   };
   };
+
   class istream : virtual public ios {
   class istream : virtual public ios {
   __published:
   __published:
     istream(const istream&) = delete;
     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();
     int get();
     streampos tellg();
     streampos tellg();
     void seekg(streampos pos);
     void seekg(streampos pos);
@@ -55,6 +67,7 @@ namespace std {
   protected:
   protected:
     istream(istream &&);
     istream(istream &&);
   };
   };
+
   class iostream : public istream, public ostream {
   class iostream : public istream, public ostream {
   __published:
   __published:
     iostream(const iostream&) = delete;
     iostream(const iostream&) = delete;

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

@@ -12,3 +12,27 @@
  */
  */
 
 
 #include "encryptStream.h"
 #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(key_length, get_key_length);
   MAKE_PROPERTY(iteration_count, get_iteration_count);
   MAKE_PROPERTY(iteration_count, get_iteration_count);
 
 
+public:
+  bool read_magic(const char *magic, size_t size);
+
 private:
 private:
   EncryptStreamBuf _buf;
   EncryptStreamBuf _buf;
 };
 };

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

@@ -81,3 +81,21 @@ INLINE int EncryptStreamBuf::
 get_iteration_count() const {
 get_iteration_count() const {
   return _iteration_count;
   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];
   _read_overflow_buffer = new unsigned char[_read_block_size];
   _in_read_overflow_buffer = 0;
   _in_read_overflow_buffer = 0;
+  _finished = false;
   thread_consider_yield();
   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
  * Called by the system ostream implementation when its internal buffer is
  * filled, plus one character.
  * filled, plus one character.
@@ -423,7 +475,7 @@ read_chars(char *start, size_t length) {
 
 
   do {
   do {
     // Get more bytes from the stream.
     // Get more bytes from the stream.
-    if (_read_ctx == nullptr) {
+    if (_read_ctx == nullptr || _finished) {
       return 0;
       return 0;
     }
     }
 
 
@@ -439,8 +491,7 @@ read_chars(char *start, size_t length) {
     } else {
     } else {
       result =
       result =
         EVP_DecryptFinal(_read_ctx, read_buffer, &bytes_read);
         EVP_DecryptFinal(_read_ctx, read_buffer, &bytes_read);
-      EVP_CIPHER_CTX_free(_read_ctx);
-      _read_ctx = nullptr;
+      _finished = true;
     }
     }
 
 
     if (result <= 0) {
     if (result <= 0) {

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

@@ -44,6 +44,12 @@ public:
   INLINE void set_iteration_count(int iteration_count);
   INLINE void set_iteration_count(int iteration_count);
   INLINE int get_iteration_count() const;
   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:
 protected:
   virtual int overflow(int c);
   virtual int overflow(int c);
   virtual int sync();
   virtual int sync();
@@ -71,6 +77,9 @@ private:
 
 
   EVP_CIPHER_CTX *_write_ctx;
   EVP_CIPHER_CTX *_write_ctx;
   size_t _write_block_size;
   size_t _write_block_size;
+
+  size_t _magic_length = 0;
+  bool _finished = false;
 };
 };
 
 
 #include "encryptStreamBuf.I"
 #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::
 INLINE void StreamReader::
 operator = (const StreamReader &copy) {
 operator = (const StreamReader &copy) {
@@ -54,6 +65,19 @@ operator = (const StreamReader &copy) {
   _owns_stream = false;
   _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:
 PUBLISHED:
   INLINE explicit StreamReader(std::istream *in, bool owns_stream);
   INLINE explicit StreamReader(std::istream *in, bool owns_stream);
   INLINE StreamReader(const StreamReader &copy);
   INLINE StreamReader(const StreamReader &copy);
+  INLINE StreamReader(StreamReader &&from) noexcept;
   INLINE void operator = (const StreamReader &copy);
   INLINE void operator = (const StreamReader &copy);
+  INLINE void operator = (StreamReader &&from) noexcept;
   INLINE ~StreamReader();
   INLINE ~StreamReader();
 
 
   INLINE std::istream *get_istream() const;
   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::
 INLINE void StreamWriter::
 operator = (const StreamWriter &copy) {
 operator = (const StreamWriter &copy) {
@@ -62,6 +76,19 @@ operator = (const StreamWriter &copy) {
   _owns_stream = false;
   _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:
 PUBLISHED:
   INLINE explicit StreamWriter(std::ostream *out, bool owns_stream);
   INLINE explicit StreamWriter(std::ostream *out, bool owns_stream);
   INLINE StreamWriter(const StreamWriter &copy);
   INLINE StreamWriter(const StreamWriter &copy);
+  INLINE StreamWriter(StreamWriter &&from) noexcept;
   INLINE void operator = (const StreamWriter &copy);
   INLINE void operator = (const StreamWriter &copy);
+  INLINE void operator = (StreamWriter &&from) noexcept;
   INLINE ~StreamWriter();
   INLINE ~StreamWriter();
 
 
   INLINE std::ostream *get_ostream() const;
   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')
     oscmd('rm -f Panda3D-rw.dmg')
 
 
 
 
-def MakeInstallerFreeBSD(version, runtime=False, **kwargs):
+def MakeInstallerFreeBSD(version, runtime=False, python_versions=[], **kwargs):
     outputdir = GetOutputDir()
     outputdir = GetOutputDir()
 
 
     oscmd("rm -rf targetroot +DESC pkg-plist +MANIFEST")
     oscmd("rm -rf targetroot +DESC pkg-plist +MANIFEST")
@@ -758,7 +758,7 @@ def MakeInstallerFreeBSD(version, runtime=False, **kwargs):
     if runtime:
     if runtime:
         InstallRuntime(destdir="targetroot", prefix="/usr/local", outputdir=outputdir)
         InstallRuntime(destdir="targetroot", prefix="/usr/local", outputdir=outputdir)
     else:
     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"):
     if not os.path.exists("/usr/sbin/pkg"):
         exit("Cannot create an installer without 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("  --everything      (enable every third-party lib)")
     print("  --directx-sdk=X   (specify version of DirectX SDK to use: jun2010, aug2009, mar2009, aug2006)")
     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("  --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("  --use-icl         (experimental setting to use an intel compiler instead of MSVC on Windows)")
     print("")
     print("")
     print("The simplest way to compile panda is to just type:")
     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.
     # Set this to a nice default.
     HOST_URL = "https://runtime.panda3d.org/"
     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.
 ## Choose a Compiler.
@@ -913,6 +924,10 @@ if (COMPILER=="GCC"):
         else:
         else:
             PkgDisable("OPENCV")
             PkgDisable("OPENCV")
 
 
+        if GetTarget() == "darwin" and not PkgSkip("OPENAL"):
+            LibName("OPENAL", "-framework AudioToolbox")
+            LibName("OPENAL", "-framework CoreAudio")
+
         if not PkgSkip("ASSIMP") and \
         if not PkgSkip("ASSIMP") and \
             os.path.isfile(GetThirdpartyDir() + "assimp/lib/libassimp.a"):
             os.path.isfile(GetThirdpartyDir() + "assimp/lib/libassimp.a"):
             # Also pick up IrrXML, which is needed when linking statically.
             # Also pick up IrrXML, which is needed when linking statically.
@@ -998,12 +1013,26 @@ if (COMPILER=="GCC"):
 
 
     if GetTarget() == 'darwin':
     if GetTarget() == 'darwin':
         LibName("ALWAYS", "-framework AppKit")
         LibName("ALWAYS", "-framework AppKit")
+        LibName("IOKIT", "-framework IOKit")
+        LibName("QUARTZ", "-framework Quartz")
         LibName("AGL", "-framework AGL")
         LibName("AGL", "-framework AGL")
         LibName("CARBON", "-framework Carbon")
         LibName("CARBON", "-framework Carbon")
         LibName("COCOA", "-framework Cocoa")
         LibName("COCOA", "-framework Cocoa")
         # Fix for a bug in OSX Leopard:
         # 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")
         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':
     if GetTarget() == 'android':
         LibName("ALWAYS", '-llog')
         LibName("ALWAYS", '-llog')
         LibName("ANDROID", '-landroid')
         LibName("ANDROID", '-landroid')
@@ -1129,6 +1158,7 @@ def BracketNameWithQuotes(name):
     # Workaround for OSX bug - compiler doesn't like those flags quoted.
     # Workaround for OSX bug - compiler doesn't like those flags quoted.
     if (name.startswith("-framework")): return name
     if (name.startswith("-framework")): return name
     if (name.startswith("-dylib_file")): return name
     if (name.startswith("-dylib_file")): return name
+    if (name.startswith("-undefined ")): return name
 
 
     # Don't add quotes when it's not necessary.
     # Don't add quotes when it's not necessary.
     if " " not in name: return name
     if " " not in name: return name
@@ -1802,9 +1832,11 @@ def CompileLink(dll, obj, opts):
                 cmd += ' -Wl,--allow-shlib-undefined'
                 cmd += ' -Wl,--allow-shlib-undefined'
         else:
         else:
             if (GetTarget() == "darwin"):
             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:
                 else:
                     install_name = '@loader_path/../lib/' + os.path.basename(dll)
                     install_name = '@loader_path/../lib/' + os.path.basename(dll)
                     cmd += ' -dynamiclib -install_name ' + install_name
                     cmd += ' -dynamiclib -install_name ' + install_name
@@ -2314,7 +2346,6 @@ DTOOL_CONFIG=[
     ("COMPILE_IN_DEFAULT_FONT",        '1',                      '1'),
     ("COMPILE_IN_DEFAULT_FONT",        '1',                      '1'),
     ("STDFLOAT_DOUBLE",                'UNDEF',                  'UNDEF'),
     ("STDFLOAT_DOUBLE",                'UNDEF',                  'UNDEF'),
     ("HAVE_MAYA",                      '1',                      '1'),
     ("HAVE_MAYA",                      '1',                      '1'),
-    ("HAVE_SOFTIMAGE",                 'UNDEF',                  'UNDEF'),
     ("REPORT_OPENSSL_ERRORS",          '1',                      '1'),
     ("REPORT_OPENSSL_ERRORS",          '1',                      '1'),
     ("USE_PANDAFILESTREAM",            '1',                      '1'),
     ("USE_PANDAFILESTREAM",            '1',                      '1'),
     ("USE_DELETED_CHAIN",              '1',                      '1'),
     ("USE_DELETED_CHAIN",              '1',                      '1'),
@@ -2855,6 +2886,14 @@ for basename in del_files:
 p3d_init = """"Python bindings for the Panda3D libraries"
 p3d_init = """"Python bindings for the Panda3D libraries"
 
 
 __version__ = '%s'
 __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)
 """ % (WHLVERSION)
 
 
 if GetTarget() == 'windows':
 if GetTarget() == 'windows':
@@ -3003,9 +3042,6 @@ else:
 if (GetTarget() == 'darwin'):
 if (GetTarget() == 'darwin'):
     configprc = configprc.replace("$XDG_CACHE_HOME/panda3d", "$HOME/Library/Caches/Panda3D-%s" % MAJOR_VERSION)
     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':
 if GetTarget() == 'windows':
     # Convert to Windows newlines.
     # Convert to Windows newlines.
     ConditionalWriteFile(GetOutputDir()+"/etc/Config.prc", configprc, newline='\r\n')
     ConditionalWriteFile(GetOutputDir()+"/etc/Config.prc", configprc, newline='\r\n')
@@ -3654,6 +3690,7 @@ IGATEFILES += [
     "globPattern_ext.h",
     "globPattern_ext.h",
     "pandaFileStream.h",
     "pandaFileStream.h",
     "lineStream.h",
     "lineStream.h",
+    "iostream_ext.h",
 ]
 ]
 TargetAdd('libp3dtoolutil.in', opts=OPTS, input=IGATEFILES)
 TargetAdd('libp3dtoolutil.in', opts=OPTS, input=IGATEFILES)
 TargetAdd('libp3dtoolutil.in', opts=['IMOD:panda3d.core', 'ILIB:libp3dtoolutil', 'SRCDIR:dtool/src/dtoolutil'])
 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"])
 IGATEFILES=GetDirectoryContents('panda/src/downloader', ["*.h", "*_composite*.cxx"])
 TargetAdd('libp3downloader.in', opts=OPTS, input=IGATEFILES)
 TargetAdd('libp3downloader.in', opts=OPTS, input=IGATEFILES)
 TargetAdd('libp3downloader.in', opts=['IMOD:panda3d.core', 'ILIB:libp3downloader', 'SRCDIR:panda/src/downloader'])
 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/
 # DIRECTORY: panda/metalibs/pandaexpress/
@@ -3985,12 +4021,12 @@ if (not RUNTIME):
 #
 #
 
 
 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_graphicsStateGuardian.obj', opts=OPTS, input='graphicsStateGuardian.cxx')
   TargetAdd('p3display_composite1.obj', opts=OPTS, input='p3display_composite1.cxx')
   TargetAdd('p3display_composite1.obj', opts=OPTS, input='p3display_composite1.cxx')
   TargetAdd('p3display_composite2.obj', opts=OPTS, input='p3display_composite2.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=GetDirectoryContents('panda/src/display', ["*.h", "*_composite*.cxx"])
   IGATEFILES.remove("renderBuffer.h")
   IGATEFILES.remove("renderBuffer.h")
   TargetAdd('libp3display.in', opts=OPTS, input=IGATEFILES)
   TargetAdd('libp3display.in', opts=OPTS, input=IGATEFILES)
@@ -4209,7 +4245,7 @@ if (not RUNTIME):
   OPTS=['DIR:panda/metalibs/panda', 'BUILDING:PANDA', 'JPEG', 'PNG', 'HARFBUZZ',
   OPTS=['DIR:panda/metalibs/panda', 'BUILDING:PANDA', 'JPEG', 'PNG', 'HARFBUZZ',
       'TIFF', 'OPENEXR', 'ZLIB', 'OPENSSL', 'FREETYPE', 'FFTW', 'ADVAPI', 'WINSOCK2',
       'TIFF', 'OPENEXR', 'ZLIB', 'OPENSSL', 'FREETYPE', 'FFTW', 'ADVAPI', 'WINSOCK2',
       'SQUISH', 'NVIDIACG', 'VORBIS', 'OPUS', 'WINUSER', 'WINMM', 'WINGDI', 'IPHLPAPI',
       'SQUISH', 'NVIDIACG', 'VORBIS', 'OPUS', 'WINUSER', 'WINMM', 'WINGDI', 'IPHLPAPI',
-      'SETUPAPI']
+      'SETUPAPI', 'IOKIT']
 
 
   TargetAdd('panda_panda.obj', opts=OPTS, input='panda.cxx')
   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='p3prc_ext_composite.obj')
 
 
   PyTargetAdd('core.pyd', input='libp3downloader_igate.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='p3express_ext_composite.obj')
   PyTargetAdd('core.pyd', input='libp3express_igate.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')
   TargetAdd('p3egg2pg_composite2.obj', opts=OPTS, input='p3egg2pg_composite2.cxx')
 
 
   OPTS=['DIR:panda/src/egg2pg']
   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=OPTS, input=IGATEFILES)
   TargetAdd('libp3egg2pg.in', opts=['IMOD:panda3d.egg', 'ILIB:libp3egg2pg', 'SRCDIR:panda/src/egg2pg'])
   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):
   if (PkgSkip('PANDAFX')==0):
     TargetAdd('libpandagl.dll', input='libpandafx.dll')
     TargetAdd('libpandagl.dll', input='libpandafx.dll')
   TargetAdd('libpandagl.dll', input=COMMON_PANDA_LIBS)
   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/
 # DIRECTORY: panda/src/wgldisplay/
@@ -5172,7 +5207,7 @@ if (not RUNTIME and GetTarget() == 'android'):
     TargetAdd('libppython.dll', input='libp3framework.dll')
     TargetAdd('libppython.dll', input='libp3framework.dll')
     TargetAdd('libppython.dll', input='libp3android.dll')
     TargetAdd('libppython.dll', input='libp3android.dll')
     TargetAdd('libppython.dll', input=COMMON_PANDA_LIBS)
     TargetAdd('libppython.dll', input=COMMON_PANDA_LIBS)
-    TargetAdd('libppython.dll', opts=['MODULE', 'ANDROID'])
+    TargetAdd('libppython.dll', opts=['MODULE', 'ANDROID', 'PYTHON'])
 
 
 #
 #
 # DIRECTORY: panda/src/androiddisplay/
 # 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):
 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_composite1.obj', opts=OPTS, input='p3tinydisplay_composite1.cxx')
   TargetAdd('p3tinydisplay_composite2.obj', opts=OPTS, input='p3tinydisplay_composite2.cxx')
   TargetAdd('p3tinydisplay_composite2.obj', opts=OPTS, input='p3tinydisplay_composite2.cxx')
   TargetAdd('p3tinydisplay_ztriangle_1.obj', opts=OPTS, input='ztriangle_1.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\test_types.cxx"></File>
 				<File RelativePath="..\panda\src\express\weakPointerTo.I"></File>
 				<File RelativePath="..\panda\src\express\weakPointerTo.I"></File>
 				<File RelativePath="..\panda\src\express\pta_int.cxx"></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\namable.I"></File>
 				<File RelativePath="..\panda\src\express\vector_float.cxx"></File>
 				<File RelativePath="..\panda\src\express\vector_float.cxx"></File>
 				<File RelativePath="..\panda\src\express\pointerTo.h"></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\datagramGenerator.h"></File>
 				<File RelativePath="..\panda\src\express\weakPointerToVoid.h"></File>
 				<File RelativePath="..\panda\src\express\weakPointerToVoid.h"></File>
 				<File RelativePath="..\panda\src\express\datagram.I"></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\weakPointerCallback.h"></File>
 				<File RelativePath="..\panda\src\express\datagram.h"></File>
 				<File RelativePath="..\panda\src\express\datagram.h"></File>
 				<File RelativePath="..\panda\src\express\textEncoder.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\typedReferenceCount.h"></File>
 				<File RelativePath="..\panda\src\express\virtualFileMountSystem.I"></File>
 				<File RelativePath="..\panda\src\express\virtualFileMountSystem.I"></File>
 				<File RelativePath="..\panda\src\express\nodePointerTo.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\hashVal.I"></File>
 				<File RelativePath="..\panda\src\express\pta_float.cxx"></File>
 				<File RelativePath="..\panda\src\express\pta_float.cxx"></File>
 				<File RelativePath="..\panda\src\express\weakPointerTo.h"></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\pointerToArrayBase.I"></File>
 				<File RelativePath="..\panda\src\express\datagramIterator.I"></File>
 				<File RelativePath="..\panda\src\express\datagramIterator.I"></File>
 				<File RelativePath="..\panda\src\express\vector_uchar.h"></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\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\datagramGenerator.cxx"></File>
 				<File RelativePath="..\panda\src\express\hashGeneratorBase.h"></File>
 				<File RelativePath="..\panda\src\express\hashGeneratorBase.h"></File>
 				<File RelativePath="..\panda\src\express\patchfile.cxx"></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\namable.cxx"></File>
 				<File RelativePath="..\panda\src\express\trueClock.I"></File>
 				<File RelativePath="..\panda\src\express\trueClock.I"></File>
 				<File RelativePath="..\panda\src\express\config_express.cxx"></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\pointerToVoid.I"></File>
 				<File RelativePath="..\panda\src\express\vector_uchar.cxx"></File>
 				<File RelativePath="..\panda\src\express\vector_uchar.cxx"></File>
 				<File RelativePath="..\panda\src\express\vector_float.h"></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\datagramGenerator.I"></File>
 				<File RelativePath="..\panda\src\express\compress_string.cxx"></File>
 				<File RelativePath="..\panda\src\express\compress_string.cxx"></File>
 				<File RelativePath="..\panda\src\express\subStreamBuf.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\pointerToArrayBase.cxx"></File>
 				<File RelativePath="..\panda\src\express\express_composite.cxx"></File>
 				<File RelativePath="..\panda\src\express\express_composite.cxx"></File>
 				<File RelativePath="..\panda\src\express\virtualFileComposite.I"></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\multifile.I"></File>
 				<File RelativePath="..\panda\src\express\virtualFile.I"></File>
 				<File RelativePath="..\panda\src\express\virtualFile.I"></File>
 				<File RelativePath="..\panda\src\express\patchfile.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>
 				<File RelativePath="..\panda\src\express\virtualFileList.h"></File>
 			</Filter>
 			</Filter>
 			<Filter Name="iphonedisplay">
 			<Filter Name="iphonedisplay">

+ 9 - 2
makepanda/makepandacore.py

@@ -78,6 +78,7 @@ MSVCVERSIONINFO = {
     (12,0): {"vsversion":(12,0), "vsname":"Visual Studio 2013"},
     (12,0): {"vsversion":(12,0), "vsname":"Visual Studio 2013"},
     (14,0): {"vsversion":(14,0), "vsname":"Visual Studio 2015"},
     (14,0): {"vsversion":(14,0), "vsname":"Visual Studio 2015"},
     (14,1): {"vsversion":(15,0), "vsname":"Visual Studio 2017"},
     (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('\\'):
         elif not win_kit.endswith('\\'):
             win_kit += '\\'
             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.
         # Copy the DLLs to the bin directory.
         CopyAllFiles(GetOutputDir() + "/bin/", win_kit + "Redist\\ucrt\\DLLs\\" + arch + "\\")
         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
     # 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.
     # 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}'
 __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.
     # Copy the extension modules from the panda3d directory.
     ext_suffix = GetExtensionSuffix()
     ext_suffix = GetExtensionSuffix()

+ 16 - 13
makepanda/test_wheel.py

@@ -17,31 +17,34 @@ from optparse import OptionParser
 def test_wheel(wheel, verbose=False):
 def test_wheel(wheel, verbose=False):
     envdir = tempfile.mkdtemp(prefix="venv-")
     envdir = tempfile.mkdtemp(prefix="venv-")
     print("Setting up virtual environment in {0}".format(envdir))
     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):
     if sys.version_info >= (3, 0):
-        subprocess.call([sys.executable, "-m", "venv", "--clear", envdir])
+        subprocess.call([sys.executable, "-B", "-m", "venv", "--clear", envdir])
     else:
     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)
         shutil.rmtree(envdir)
         sys.exit(1)
         sys.exit(1)
 
 
     # Install pytest into the environment, as well as our wheel.
     # 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)
         shutil.rmtree(envdir)
         sys.exit(1)
         sys.exit(1)
 
 
     # Run the test suite.
     # 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"]
     test_cmd = [python, "-m", "pytest", "tests"]
     if verbose:
     if verbose:
         test_cmd.append("--verbose")
         test_cmd.append("--verbose")

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

@@ -11,12 +11,12 @@
  * @date 2000-07-06
  * @date 2000-07-06
  */
  */
 
 
-#ifndef __AUDIO_H__
-#define __AUDIO_H__
+#ifndef AUDIO_H
+#define AUDIO_H
 
 
 #include "filterProperties.h"
 #include "filterProperties.h"
 #include "audioLoadRequest.h"
 #include "audioLoadRequest.h"
 #include "audioSound.h"
 #include "audioSound.h"
 #include "audioManager.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 {
 write(std::ostream &out) const {
   out << (*this) << "\n";
   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
  * Prior system by: cary
  */
  */
 
 
-#ifndef __AUDIO_MANAGER_H__
-#define __AUDIO_MANAGER_H__
+#ifndef AUDIOMANAGER_H
+#define AUDIOMANAGER_H
 
 
 #include "config_audio.h"
 #include "config_audio.h"
 #include "audioSound.h"
 #include "audioSound.h"
@@ -178,9 +178,6 @@ PUBLISHED:
   virtual void output(std::ostream &out) const;
   virtual void output(std::ostream &out) const;
   virtual void write(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:
 public:
   static void register_AudioManager_creator(Create_AudioManager_proc* proc);
   static void register_AudioManager_creator(Create_AudioManager_proc* proc);
 
 
@@ -222,4 +219,4 @@ operator << (std::ostream &out, const AudioManager &mgr) {
 
 
 #include "audioManager.I"
 #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
     // 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.
  * Configure the local DSP filter chain.
  *
  *

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

@@ -12,8 +12,8 @@
  * Prior system by: cary
  * Prior system by: cary
  */
  */
 
 
-#ifndef __AUDIOSOUND_H__
-#define __AUDIOSOUND_H__
+#ifndef AUDIOSOUND_H
+#define AUDIOSOUND_H
 
 
 #include "config_audio.h"
 #include "config_audio.h"
 #include "typedReferenceCount.h"
 #include "typedReferenceCount.h"
@@ -104,17 +104,10 @@ PUBLISHED:
   virtual void set_3d_max_distance(PN_stdfloat dist);
   virtual void set_3d_max_distance(PN_stdfloat dist);
   virtual PN_stdfloat get_3d_max_distance() const;
   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 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 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 int get_priority();
   virtual void set_priority(int priority);
   virtual void set_priority(int priority);
 
 
@@ -160,4 +153,4 @@ operator << (std::ostream &out, const AudioSound &sound) {
 EXPCL_PANDA_AUDIO std::ostream &
 EXPCL_PANDA_AUDIO std::ostream &
 operator << (std::ostream &out, AudioSound::SoundStatus status);
 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. "));
           "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
 ConfigVariableFilename audio_dls_file
 ("audio-dls-file", Filename(),
 ("audio-dls-file", Filename(),
  PRC_DESC("Specifies a DLS file that defines an instrument set to load "
  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 "
           "one is available; the likely success of this depends on the "
           "operating system."));
           "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) {
 ConfigureFn(config_audio) {
   FilterProperties::init_type();
   FilterProperties::init_type();
   AudioLoadRequest::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 ConfigVariableInt fmod_number_of_sound_channels;
 extern EXPCL_PANDA_AUDIO ConfigVariableBool fmod_use_surround_sound;
 extern EXPCL_PANDA_AUDIO ConfigVariableBool fmod_use_surround_sound;
 extern EXPCL_PANDA_AUDIO ConfigVariableEnum<FmodSpeakerMode> fmod_speaker_mode;
 extern EXPCL_PANDA_AUDIO ConfigVariableEnum<FmodSpeakerMode> fmod_speaker_mode;
+extern EXPCL_PANDA_AUDIO ConfigVariableFilename audio_dls_file;
 
 
 // Config vars for OpenAL:
 // 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 ConfigVariableDouble audio_buffering_seconds;
 extern EXPCL_PANDA_AUDIO ConfigVariableInt    audio_preload_threshold;
 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 //[
 #ifdef NOTIFY_DEBUG //[
   // Non-release build:
   // Non-release build:
   #define audio_debug(msg) \
   #define audio_debug(msg) \

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

@@ -12,8 +12,8 @@
  * Prior system by: cary
  * Prior system by: cary
  */
  */
 
 
-#ifndef __NULL_AUDIO_MANAGER_H__
-#define __NULL_AUDIO_MANAGER_H__
+#ifndef NULLAUDIOMANAGER_H
+#define NULLAUDIOMANAGER_H
 
 
 #include "audioManager.h"
 #include "audioManager.h"
 #include "nullAudioSound.h"
 #include "nullAudioSound.h"
@@ -21,7 +21,7 @@
 class EXPCL_PANDA_AUDIO NullAudioManager : public AudioManager {
 class EXPCL_PANDA_AUDIO NullAudioManager : public AudioManager {
   // All of these methods are stubbed out to some degree.  If you're looking
   // 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
   // for a starting place for a new AudioManager, please consider looking at
-  // the milesAudioManager.
+  // the openalAudioManager.
 
 
 public:
 public:
   NullAudioManager();
   NullAudioManager();
@@ -89,4 +89,4 @@ private:
   static TypeHandle _type_handle;
   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
  * Prior system by: cary
  */
  */
 
 
-#ifndef __NULL_AUDIO_SOUND_H__
-#define __NULL_AUDIO_SOUND_H__
+#ifndef NULLAUDIOSOUND_H
+#define NULLAUDIOSOUND_H
 
 
 #include "audioSound.h"
 #include "audioSound.h"
 
 
@@ -23,7 +23,7 @@
 class EXPCL_PANDA_AUDIO NullAudioSound : public AudioSound {
 class EXPCL_PANDA_AUDIO NullAudioSound : public AudioSound {
   // All of these methods are stubbed out to some degree.  If you're looking
   // 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
   // for a starting place for a new AudioManager, please consider looking at
-  // the milesAudioManager.
+  // the openalAudioManager.
 
 
 public:
 public:
   ~NullAudioSound();
   ~NullAudioSound();
@@ -91,4 +91,4 @@ private:
   friend class NullAudioManager;
   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 channels = stream->audio_channels();
     int samples = (int)(stream->length() * stream->audio_rate());
     int samples = (int)(stream->length() * stream->audio_rate());
     int16_t *data = new int16_t[samples * channels];
     int16_t *data = new int16_t[samples * channels];
-    stream->read_samples(samples, data);
+    samples = stream->read_samples(samples, data);
     alBufferData(sd->_sample,
     alBufferData(sd->_sample,
                  (channels>1) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16,
                  (channels>1) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16,
                  data, samples * channels * 2, stream->audio_rate());
                  data, samples * channels * 2, stream->audio_rate());

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.