<commit_before>#ifndef CXX_OBJECT_HXX
# define CXX_OBJECT_HXX

# include <boost/bind.hpp>

# include <object/atom.hh>
# include <object/string-class.hh>
# include <object/object-class.hh>
# include <object/primitives.hh>

namespace object
{
  template <typename T>
  bool CxxObject::add(const std::string& name, rObject& tgt)
  {
    initializers_get().push_back(new TypeInitializer<T>(name, tgt));
    return true;
  }

  template <typename T>
  CxxObject::TypeInitializer<T>::TypeInitializer(const std::string& name,
                                                 rObject& tgt)
    : Initializer(tgt), name_(name)
  {}

  namespace
  {
    template <typename T>
    rObject cxx_object_clone(rObject parent, runner::Runner&, objects_type args)
    {
      CHECK_ARG_COUNT(1);
      rObject tgt = args[0];
      rObject res;
      if (tgt->is_a<T>())
        res = new T(tgt->as<T>());
      else
        res = new T();
      res->proto_add(parent);
      return res;
    }
  }

  template <typename T>
  void
  CxxObject::TypeInitializer<T>::create()
  {
    res_ = new Object();
  }

  template <typename T>
  rObject
  CxxObject::TypeInitializer<T>::make_class()
  {
    res_->proto_add(object_class);
    res_->slot_set(SYMBOL(protoName), new String(name_));
    res_->slot_set(SYMBOL(clone),
                   new Primitive(boost::bind(cxx_object_clone<T>,
                                             res_, _1, _2)));
    Binder<T> b(res_);
    T::initialize(b);
    return res_;
  }

  template <typename T>
  libport::Symbol
  CxxObject::TypeInitializer<T>::name()
  {
    return name_;
  }

  // BINDER

  template <typename T>
  CxxObject::Binder<T>::Binder(rObject tgt)
    : tgt_(tgt)
  {}

  namespace
  {

# define PRINT_true(X) X
# define PRINT_false(X)
# define PRINT_truetrue(X) X
# define PRINT_falsetrue(X)
# define PRINT_truefalse(X)
# define PRINT_falsefalse(X)
# define NPRINT_true(X)
# define NPRINT_false(X) X

# define WHEN(Cond, X) PRINT_##Cond(X)
# define WHEN_NOT(Cond, X) NPRINT_##Cond(X)

# define IF(Cond, Then, Else) WHEN(Cond, Then) WHEN_NOT(Cond, Else)

# define COMMA_ ,
# define COMMA(Cond) PRINT_##Cond(COMMA_)

# define COMMA2(Cond1, Cond2) PRINT_##Cond1##Cond2(COMMA_)

# define MET(Met, Name, Ret, Run, Arg1, Arg2, Arg3)     \
    IF(Ret, libport::shared_ptr<R>, void)               \
    (WHEN(Met, T::)*Name)(                              \
      WHEN(Run, runner::Runner&) COMMA2(Run, Arg1)      \
      WHEN(Arg1, libport::shared_ptr<A1>)               \
      COMMA(Arg2) WHEN(Arg2, libport::shared_ptr<A2>)   \
      COMMA(Arg3) WHEN(Arg3, libport::shared_ptr<A3>)   \
      )

#define GET_ARG(Met, N)                                                 \
    type_check<A##N>(args[N WHEN_NOT(Met, - 1)], name.name_get());     \
    libport::shared_ptr<A##N> a##N =                                   \
      args[N WHEN_NOT(Met, - 1)].unsafe_cast<A##N>();                  \
    assert(a##N);

#define FETCH_TGT()                                                     \
    type_check<T>(args[0], name.name_get());                            \
    libport::shared_ptr<T> tgt = args[0].unsafe_cast<T>();              \
    assert(tgt);                                                        \

#define PRIMITIVE(Met, Ret, ArgsC, Run, Arg1, Arg2, Arg3)               \
    template <typename T                                                \
              COMMA(Ret) WHEN(Ret, typename R)                          \
      COMMA(Arg1) WHEN(Arg1, typename A1)                               \
      COMMA(Arg2) WHEN(Arg2, typename A2)                               \
      COMMA(Arg3) WHEN(Arg3, typename A3)                               \
      >                                                                 \
    struct primitive<T, MET(Met, , Ret, Run, Arg1, Arg2, Arg3)>         \
    {                                                                   \
        static rObject make(                                            \
          MET(Met, method, Ret, Run, Arg1, Arg2, Arg3),                 \
          const libport::Symbol& IF(Met, name, WHEN(Arg1, name)),       \
          runner::Runner& WHEN(Run, r),                                 \
          objects_type args)                                            \
        {                                                               \
          assert(args.size() ==                                         \
                 ArgsC IF(Met, + 1, WHEN_NOT(Arg1, + 1)));              \
          WHEN(Met, FETCH_TGT());                                       \
          WHEN(Arg1, GET_ARG(Met, 1))                                   \
            WHEN(Arg2, GET_ARG(Met, 2))                                 \
            WHEN(Arg3, GET_ARG(Met, 3))                                 \
            WHEN(Ret, return)                                           \
            (WHEN(Met, tgt.get()->*)method)(                            \
              WHEN(Run, r) COMMA2(Run, Arg1)                            \
              WHEN(Arg1, a1)                                            \
              COMMA(Arg2) WHEN(Arg2, a2)                                \
              COMMA(Arg3) WHEN(Arg3, a3)                                \
              );                                                        \
          return void_class;                                            \
        }                                                               \
      }

    template <typename T, typename M>
    struct primitive
    {
    };

    /* Python for these:
max = 3
for ret in ('true', 'false'):
    for run in ('true', 'false'):
        for nargs in range(max + 1):
            for macro in ('PRIMITIVE ', 'PRIMITIVEF'):
                print "    %s(%s, %i, %s" % (macro, ret, nargs, run),
                for i in range(max):
                    print ", %s" % str(i < nargs).lower(),
                print ");"
    */
    PRIMITIVE(true , true, 0, true , false , false , false );
    PRIMITIVE(true , true, 1, true , true , false , false );
    PRIMITIVE(true , true, 2, true , true , true , false );
    PRIMITIVE(true , true, 3, true , true , true , true );
    PRIMITIVE(true , true, 0, false , false , false , false );
    PRIMITIVE(true , true, 1, false , true , false , false );
    PRIMITIVE(true , true, 2, false , true , true , false );
    PRIMITIVE(true , true, 3, false , true , true , true );
    PRIMITIVE(true , false, 0, true , false , false , false );
    PRIMITIVE(true , false, 1, true , true , false , false );
    PRIMITIVE(true , false, 2, true , true , true , false );
    PRIMITIVE(true , false, 3, true , true , true , true );
    PRIMITIVE(true , false, 0, false , false , false , false );
    PRIMITIVE(true , false, 1, false , true , false , false );
    PRIMITIVE(true , false, 2, false , true , true , false );
    PRIMITIVE(true , false, 3, false , true , true , true );
    PRIMITIVE(false, true, 0, true , false , false , false );
    PRIMITIVE(false, true, 1, true , true , false , false );
    PRIMITIVE(false, true, 2, true , true , true , false );
    PRIMITIVE(false, true, 3, true , true , true , true );
    PRIMITIVE(false, true, 0, false , false , false , false );
    PRIMITIVE(false, true, 1, false , true , false , false );
    PRIMITIVE(false, true, 2, false , true , true , false );
    PRIMITIVE(false, true, 3, false , true , true , true );
    PRIMITIVE(false, false, 0, true , false , false , false );
    PRIMITIVE(false, false, 1, true , true , false , false );
    PRIMITIVE(false, false, 2, true , true , true , false );
    PRIMITIVE(false, false, 3, true , true , true , true );
    PRIMITIVE(false, false, 0, false , false , false , false );
    PRIMITIVE(false, false, 1, false , true , false , false );
    PRIMITIVE(false, false, 2, false , true , true , false );
    PRIMITIVE(false, false, 3, false , true , true , true );
  }

  template <typename T>
  template <typename M>
  void CxxObject::Binder<T>::operator()(const libport::Symbol& name,
                                        M method)
  {
    // If make is unfound here, you passed an unsupported pointer type
    // to the binder.
    rObject p =
      new Primitive(boost::bind(primitive<T, M>::make,
                                method, name, _1, _2));
    tgt_->slot_set(name, p);
  }

  template <typename T>
  inline void
  type_check(rObject o, const std::string& fun)
  {
    libport::shared_ptr<CxxObject> co = o.unsafe_cast<CxxObject>();
     // FIXME: I can't fill all the source type for now since some old
     // atoms don't define type_name for now
    if (!co)
      throw object::WrongArgumentType(T::type_name, "Object", fun);
    else if (!o->is_a<T>())
      throw object::WrongArgumentType(T::type_name, co->type_name_get(), fun);
  }

  template <>
  inline void
  type_check<Object>(rObject, const std::string&)
  {}

  template <>
  inline void
  type_check<List>(rObject, const std::string&)
  {}

}

#endif
<commit_msg>Enable to take the arguments as a C++ object list.<commit_after>#ifndef CXX_OBJECT_HXX
# define CXX_OBJECT_HXX

# include <boost/bind.hpp>

# include <object/atom.hh>
# include <object/string-class.hh>
# include <object/object-class.hh>
# include <object/primitives.hh>

namespace object
{
  template <typename T>
  bool CxxObject::add(const std::string& name, rObject& tgt)
  {
    initializers_get().push_back(new TypeInitializer<T>(name, tgt));
    return true;
  }

  template <typename T>
  CxxObject::TypeInitializer<T>::TypeInitializer(const std::string& name,
                                                 rObject& tgt)
    : Initializer(tgt), name_(name)
  {}

  namespace
  {
    template <typename T>
    rObject cxx_object_clone(rObject parent, runner::Runner&, objects_type args)
    {
      CHECK_ARG_COUNT(1);
      rObject tgt = args[0];
      rObject res;
      if (tgt->is_a<T>())
        res = new T(tgt->as<T>());
      else
        res = new T();
      res->proto_add(parent);
      return res;
    }
  }

  template <typename T>
  void
  CxxObject::TypeInitializer<T>::create()
  {
    res_ = new Object();
  }

  template <typename T>
  rObject
  CxxObject::TypeInitializer<T>::make_class()
  {
    res_->proto_add(object_class);
    res_->slot_set(SYMBOL(protoName), new String(name_));
    res_->slot_set(SYMBOL(clone),
                   new Primitive(boost::bind(cxx_object_clone<T>,
                                             res_, _1, _2)));
    Binder<T> b(res_);
    T::initialize(b);
    return res_;
  }

  template <typename T>
  libport::Symbol
  CxxObject::TypeInitializer<T>::name()
  {
    return name_;
  }

  // BINDER

  template <typename T>
  CxxObject::Binder<T>::Binder(rObject tgt)
    : tgt_(tgt)
  {}

  namespace
  {

# define PRINT_true(X) X
# define PRINT_false(X)
# define PRINT_truetrue(X) X
# define PRINT_falsetrue(X)
# define PRINT_truefalse(X)
# define PRINT_falsefalse(X)
# define NPRINT_true(X)
# define NPRINT_false(X) X

# define WHEN(Cond, X) PRINT_##Cond(X)
# define WHEN_NOT(Cond, X) NPRINT_##Cond(X)

# define IF(Cond, Then, Else) WHEN(Cond, Then) WHEN_NOT(Cond, Else)

# define COMMA_ ,
# define COMMA(Cond) PRINT_##Cond(COMMA_)

# define COMMA2(Cond1, Cond2) PRINT_##Cond1##Cond2(COMMA_)

# define MET(Met, Name, Ret, Run, Arg1, Arg2, Arg3)     \
    IF(Ret, libport::shared_ptr<R>, void)               \
    (WHEN(Met, T::)*Name)(                              \
      WHEN(Run, runner::Runner&) COMMA2(Run, Arg1)      \
      WHEN(Arg1, libport::shared_ptr<A1>)               \
      COMMA(Arg2) WHEN(Arg2, libport::shared_ptr<A2>)   \
      COMMA(Arg3) WHEN(Arg3, libport::shared_ptr<A3>)   \
      )

#define GET_ARG(Met, N)                                                 \
    type_check<A##N>(args[N WHEN_NOT(Met, - 1)], name.name_get());     \
    libport::shared_ptr<A##N> a##N =                                   \
      args[N WHEN_NOT(Met, - 1)].unsafe_cast<A##N>();                  \
    assert(a##N);

#define FETCH_TGT()                                                     \
    type_check<T>(args[0], name.name_get());                            \
    libport::shared_ptr<T> tgt = args[0].unsafe_cast<T>();

#define PRIMITIVE(Met, Ret, ArgsC, Run, Arg1, Arg2, Arg3)               \
    template <typename T                                                \
              COMMA(Ret) WHEN(Ret, typename R)                          \
      COMMA(Arg1) WHEN(Arg1, typename A1)                               \
      COMMA(Arg2) WHEN(Arg2, typename A2)                               \
      COMMA(Arg3) WHEN(Arg3, typename A3)                               \
      >                                                                 \
    struct primitive<T, MET(Met, , Ret, Run, Arg1, Arg2, Arg3)>         \
    {                                                                   \
        static rObject make(                                            \
          MET(Met, method, Ret, Run, Arg1, Arg2, Arg3),                 \
          const libport::Symbol& IF(Met, name, WHEN(Arg1, name)),       \
          runner::Runner& WHEN(Run, r),                                 \
          objects_type args)                                            \
        {                                                               \
          assert(args.size() ==                                         \
                 ArgsC IF(Met, + 1, WHEN_NOT(Arg1, + 1)));              \
          WHEN(Met, FETCH_TGT());                                       \
          WHEN(Arg1, GET_ARG(Met, 1))                                   \
            WHEN(Arg2, GET_ARG(Met, 2))                                 \
            WHEN(Arg3, GET_ARG(Met, 3))                                 \
            WHEN(Ret, return)                                           \
            (WHEN(Met, tgt.get()->*)method)(                            \
              WHEN(Run, r) COMMA2(Run, Arg1)                            \
              WHEN(Arg1, a1)                                            \
              COMMA(Arg2) WHEN(Arg2, a2)                                \
              COMMA(Arg3) WHEN(Arg3, a3)                                \
              );                                                        \
          return void_class;                                            \
        }                                                               \
      }

#define LIST_MET(Name, Met, Ret, Run)                                  \
    IF(Ret, R, void)                                                   \
    (WHEN(Met, T::)*Name)(WHEN(Run, runner::Runner&) COMMA(Run)        \
                          objects_type)                                \

#define LIST_PRIMITIVE(Met, Ret, Run)                                   \
    template <typename T                                                \
              COMMA(Ret) WHEN(Ret, typename R)                          \
      >                                                                 \
    struct primitive<T, LIST_MET(, Met, Ret, Run)>                      \
    {                                                                   \
        static rObject make(                                            \
          LIST_MET(method, Met, Ret, Run),                              \
          const libport::Symbol& name,                                  \
          runner::Runner& WHEN(Run, r),                                 \
          objects_type args)                                            \
        {                                                               \
          WHEN(Met, FETCH_TGT());                                       \
          WHEN(Met, args.pop_front());                                  \
          WHEN(Ret, return)                                             \
            (WHEN(Met, tgt.get()->*)method)(                            \
              WHEN(Run, r) COMMA(Run)                                   \
              args                                                      \
              );                                                        \
          return void_class;                                            \
        }                                                               \
      }

    template <typename T, typename M>
    struct primitive
    {
    };

    /* Python for these:
for met in ('true', 'false'):
    for ret in ('true', 'false'):
        for run in ('true', 'false'):
            print "    LIST_PRIMITIVE(%s, %s, %s);" % (met, ret, run)
     */
    LIST_PRIMITIVE(true, true, true);
    LIST_PRIMITIVE(true, true, false);
    LIST_PRIMITIVE(true, false, true);
    LIST_PRIMITIVE(true, false, false);
    LIST_PRIMITIVE(false, true, true);
    LIST_PRIMITIVE(false, true, false);
    LIST_PRIMITIVE(false, false, true);
    LIST_PRIMITIVE(false, false, false);

    /* Python for these:
max = 3
for ret in ('true', 'false'):
    for run in ('true', 'false'):
        for nargs in range(max + 1):
            for macro in ('PRIMITIVE ', 'PRIMITIVEF'):
                print "    %s(%s, %i, %s" % (macro, ret, nargs, run),
                for i in range(max):
                    print ", %s" % str(i < nargs).lower(),
                print ");"
    */
    PRIMITIVE(true , true, 0, true , false , false , false );
    PRIMITIVE(true , true, 1, true , true , false , false );
    PRIMITIVE(true , true, 2, true , true , true , false );
    PRIMITIVE(true , true, 3, true , true , true , true );
    PRIMITIVE(true , true, 0, false , false , false , false );
    PRIMITIVE(true , true, 1, false , true , false , false );
    PRIMITIVE(true , true, 2, false , true , true , false );
    PRIMITIVE(true , true, 3, false , true , true , true );
    PRIMITIVE(true , false, 0, true , false , false , false );
    PRIMITIVE(true , false, 1, true , true , false , false );
    PRIMITIVE(true , false, 2, true , true , true , false );
    PRIMITIVE(true , false, 3, true , true , true , true );
    PRIMITIVE(true , false, 0, false , false , false , false );
    PRIMITIVE(true , false, 1, false , true , false , false );
    PRIMITIVE(true , false, 2, false , true , true , false );
    PRIMITIVE(true , false, 3, false , true , true , true );
    PRIMITIVE(false, true, 0, true , false , false , false );
    PRIMITIVE(false, true, 1, true , true , false , false );
    PRIMITIVE(false, true, 2, true , true , true , false );
    PRIMITIVE(false, true, 3, true , true , true , true );
    PRIMITIVE(false, true, 0, false , false , false , false );
    PRIMITIVE(false, true, 1, false , true , false , false );
    PRIMITIVE(false, true, 2, false , true , true , false );
    PRIMITIVE(false, true, 3, false , true , true , true );
    PRIMITIVE(false, false, 0, true , false , false , false );
    PRIMITIVE(false, false, 1, true , true , false , false );
    PRIMITIVE(false, false, 2, true , true , true , false );
    PRIMITIVE(false, false, 3, true , true , true , true );
    PRIMITIVE(false, false, 0, false , false , false , false );
    PRIMITIVE(false, false, 1, false , true , false , false );
    PRIMITIVE(false, false, 2, false , true , true , false );
    PRIMITIVE(false, false, 3, false , true , true , true );
  }

  template <typename T>
  template <typename M>
  void CxxObject::Binder<T>::operator()(const libport::Symbol& name,
                                        M method)
  {
    // If make is unfound here, you passed an unsupported pointer type
    // to the binder.
    rObject p =
      new Primitive(boost::bind(primitive<T, M>::make,
                                method, name, _1, _2));
    tgt_->slot_set(name, p);
  }

  template <typename T>
  inline void
  type_check(rObject o, const std::string& fun)
  {
    libport::shared_ptr<CxxObject> co = o.unsafe_cast<CxxObject>();
     // FIXME: I can't fill all the source type for now since some old
     // atoms don't define type_name for now
    if (!co)
      throw object::WrongArgumentType(T::type_name, "Object", fun);
    else if (!o->is_a<T>())
      throw object::WrongArgumentType(T::type_name, co->type_name_get(), fun);
  }

  template <>
  inline void
  type_check<Object>(rObject, const std::string&)
  {}

  template <>
  inline void
  type_check<List>(rObject, const std::string&)
  {}

}

#endif
<|endoftext|>


<commit_before>#include "Receiver.h"
#include "ofGraphics.h"
#include "Utils.h"

namespace ofxSpout {
	//----------
	Receiver::Receiver() :
		defaultFormat(GL_RGBA) {
		this->spoutReceiver = nullptr;
		this->width = 0;
		this->height = 0;
	}

	//----------
	Receiver::~Receiver() {
		this->release();
	}

	//----------
	bool Receiver::init(std::string channelName) {
		this->release();

		try {
			this->spoutReceiver = new SpoutReceiver();
			//name provided, so let's use it
			char mutableName[256];
			strcpy_s(mutableName, channelName.size() + 1, channelName.c_str());
			unsigned int mutableWidth, mutableHeight;
			if (!this->spoutReceiver->CreateReceiver(mutableName, mutableWidth, mutableHeight, channelName.empty())) {
				throw("Can't create receiver");
			}
			this->channelName = std::string(mutableName);
			this->width = mutableWidth;
			this->height = mutableHeight;
			return true;
		}
		catch (const char * e) {
			ofLogError("ofxSpout::Sender::init") << "Channel : " << channelName << " : " << e;
			return false;
		}
	}

	//----------
	void Receiver::release() {
		if (this->isInitialized()) {
			this->spoutReceiver->ReleaseReceiver();
			delete this->spoutReceiver;
			this->spoutReceiver = nullptr;
			this->width = 0;
			this->height = 0;
		}
	}

	//----------
	bool Receiver::isInitialized() const {
		if (this->spoutReceiver) {
			return true;
		}
		else {
			return false;
		}
	}

	//----------
	bool Receiver::receive(ofTexture & texture) {
		try {
			//check if we're initialised
			if (!this->isInitialized()) {
				throw("Not initialized");
			}

			//prepare the channel name, allow it to be changed if different channels are available
			char mutableName[256];
			unsigned int mutableWidth, mutableHeight;
			strcpy_s(mutableName, this->channelName.size() + 1, this->channelName.c_str());

			//check if the texture is allocated correctly, if not, allocate it
			if (texture.getWidth() != this->width || texture.getHeight() != this->height) {
				int format = texture.isAllocated() ? texture.getTextureData().glInternalFormat : this->defaultFormat;
				texture.allocate(width, height, format);
			}

			//pull data into the texture (keep any existing fbo attachments)
			GLint drawFboId = 0;
			glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &drawFboId);
			if (!this->spoutReceiver->ReceiveTexture(mutableName, mutableWidth, mutableHeight, texture.getTextureData().textureID, texture.getTextureData().textureTarget, false, drawFboId)) {
				throw("Can't receive texture");
			}

			//update our local settings incase anything changed
			this->channelName = mutableName;
			this->width = mutableWidth;
			this->height = mutableHeight;

			return true;
		}
		catch (const char * e) {
			ofLogError("ofxSpout::Receiver::receive") << e;
			return false;
		}
	}

	//----------
	bool Receiver::selectSenderPanel() {
		try {
			if (!this->isInitialized()) {
				throw("Not initialized");
			}
			this->spoutReceiver->SelectSenderPanel();
			return true;
		}
		catch (const char * e) {
			ofLogError("ofxSpout::Receiver::selectSenderPanel") << e;
			return false;
		}
	}

	//-----------
	std::string Receiver::getChannelName() const {
		return this->channelName;
	}

	//----------
	float Receiver::getWidth() const {
		return this->width;
	}

	//----------
	float Receiver::getHeight() const {
		return this->height;
	}
}<commit_msg>Update Receiver to use 2.007 API.<commit_after>#include "Receiver.h"
#include "ofGraphics.h"
#include "Utils.h"

namespace ofxSpout {
	//----------
	Receiver::Receiver() :
		defaultFormat(GL_RGBA) {
		this->spoutReceiver = nullptr;
		this->width = 0;
		this->height = 0;
	}

	//----------
	Receiver::~Receiver() {
		this->release();
	}

	//----------
	bool Receiver::init(std::string channelName) {
		this->release();

		try {
			this->spoutReceiver = new SpoutReceiver();
			//name provided, so let's use it
			if (!channelName.empty()) {
				this->channelName = channelName;
				this->spoutReceiver->SetReceiverName(channelName.c_str());
			}
			return true;
		}
		catch (const char * e) {
			ofLogError("ofxSpout::Sender::init") << "Channel : " << channelName << " : " << e;
			return false;
		}
	}

	//----------
	void Receiver::release() {
		if (this->isInitialized()) {
			this->spoutReceiver->ReleaseReceiver();
			delete this->spoutReceiver;
			this->spoutReceiver = nullptr;
			this->width = 0;
			this->height = 0;
		}
	}

	//----------
	bool Receiver::isInitialized() const {
		if (this->spoutReceiver) {
			return true;
		}
		else {
			return false;
		}
	}

	//----------
	bool Receiver::receive(ofTexture & texture) {
		try {
			//check if we're initialised
			if (!this->isInitialized()) {
				throw("Not initialized");
			}

			//prepare the channel name, allow it to be changed if different channels are available
			char mutableName[256];
			unsigned int mutableWidth, mutableHeight;
			strcpy_s(mutableName, this->channelName.size() + 1, this->channelName.c_str());

			//check if the texture is allocated correctly, if not, allocate it
			if (this->spoutReceiver->IsUpdated()) {
				this->channelName = this->spoutReceiver->GetSenderName();
				this->width = this->spoutReceiver->GetSenderWidth();
				this->height = this->spoutReceiver->GetSenderHeight();
				texture.allocate(this->width, this->height, GL_RGBA);
			}

			//pull data into the texture (keep any existing fbo attachments)
			GLint drawFboId = 0;
			glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &drawFboId);
			if (!this->spoutReceiver->ReceiveTextureData(texture.getTextureData().textureID, texture.getTextureData().textureTarget, drawFboId)) {
				throw("Can't receive texture");
			}

			return true;
		}
		catch (const char * e) {
			ofLogError("ofxSpout::Receiver::receive") << e;
			return false;
		}
	}

	//----------
	bool Receiver::selectSenderPanel() {
		try {
			if (!this->isInitialized()) {
				throw("Not initialized");
			}
			this->spoutReceiver->SelectSender();
			return true;
		}
		catch (const char * e) {
			ofLogError("ofxSpout::Receiver::selectSenderPanel") << e;
			return false;
		}
	}

	//-----------
	std::string Receiver::getChannelName() const {
		return this->channelName;
	}

	//----------
	float Receiver::getWidth() const {
		return this->width;
	}

	//----------
	float Receiver::getHeight() const {
		return this->height;
	}
}<|endoftext|>


<commit_before>/*-----------------------------------------------------------------------------
|  Copyright (c) 2012, Enthought, Inc.
|  All rights reserved.
|----------------------------------------------------------------------------*/
#include "catom.h"
#include "member.h"
#include "event.h"
#include "signal.h"

extern "C" {

static PyMethodDef
catom_methods[] = {
    { 0 } // Sentinel
};

PyMODINIT_FUNC
initcatom( void )
{
    PyObject* mod = Py_InitModule( "catom", catom_methods );
    if( !mod )
        return;
    if( import_member() < 0 )
        return;
    if( import_catom() < 0 )
        return;
    if( import_event() < 0 )
        return;
    if( import_signal() < 0 )
        return;
    Py_INCREF( &MemberChange_Type );
    Py_INCREF( &Member_Type );
    Py_INCREF( &CAtom_Type );
    Py_INCREF( &Event_Type );
    Py_INCREF( &Signal_Type );
    Py_INCREF( _py_null );
    PyModule_AddObject( mod, "MemberChange", reinterpret_cast<PyObject*>( &MemberChange_Type ) );
    PyModule_AddObject( mod, "Member", reinterpret_cast<PyObject*>( &Member_Type ) );
    PyModule_AddObject( mod, "Event", reinterpret_cast<PyObject*>( &Event_Type ) );
    PyModule_AddObject( mod, "Signal", reinterpret_cast<PyObject*>( &Signal_Type ) );
    PyModule_AddObject( mod, "CAtom", reinterpret_cast<PyObject*>( &CAtom_Type ) );
    PyModule_AddObject( mod, "null", _py_null );
    PyModule_AddIntConstant( mod, "NO_VALIDATE", NoValidate );
    PyModule_AddIntConstant( mod, "VALIDATE_READ_ONLY", ValidateReadOnly );
    PyModule_AddIntConstant( mod, "VALIDATE_CONSTANT", ValidateConstant );
    PyModule_AddIntConstant( mod, "VALIDATE_BOOL", ValidateBool );
    PyModule_AddIntConstant( mod, "VALIDATE_INT", ValidateInt );
    PyModule_AddIntConstant( mod, "VALIDATE_LONG", ValidateLong );
    PyModule_AddIntConstant( mod, "VALIDATE_FLOAT", ValidateFloat );
    PyModule_AddIntConstant( mod, "VALIDATE_STR", ValidateStr );
    PyModule_AddIntConstant( mod, "VALIDATE_UNICODE", ValidateUnicode );
    PyModule_AddIntConstant( mod, "VALIDATE_TUPLE", ValidateTuple );
    PyModule_AddIntConstant( mod, "VALIDATE_LIST", ValidateList );
    PyModule_AddIntConstant( mod, "VALIDATE_DICT", ValidateDict );
    PyModule_AddIntConstant( mod, "VALIDATE_INSTANCE", ValidateInstance );
    PyModule_AddIntConstant( mod, "VALIDATE_TYPED", ValidateTyped );
    PyModule_AddIntConstant( mod, "VALIDATE_ENUM", ValidateEnum );
    PyModule_AddIntConstant( mod, "VALIDATE_OWNER_METHOD", ValidateOwnerMethod );
    PyModule_AddIntConstant( mod, "USER_VALIDATE", UserValidate );
    PyModule_AddIntConstant( mod, "DEFAULT_VALUE", DefaultValue );
    PyModule_AddIntConstant( mod, "DEFAULT_FACTORY", DefaultFactory );
    PyModule_AddIntConstant( mod, "DEFAULT_OWNER_METHOD", DefaultOwnerMethod );
    PyModule_AddIntConstant( mod, "USER_DEFAULT", UserDefault );
}

} // extern C

<commit_msg>Add promoted unicode and callable validator enum values<commit_after>/*-----------------------------------------------------------------------------
|  Copyright (c) 2012, Enthought, Inc.
|  All rights reserved.
|----------------------------------------------------------------------------*/
#include "catom.h"
#include "member.h"
#include "event.h"
#include "signal.h"

extern "C" {

static PyMethodDef
catom_methods[] = {
    { 0 } // Sentinel
};

PyMODINIT_FUNC
initcatom( void )
{
    PyObject* mod = Py_InitModule( "catom", catom_methods );
    if( !mod )
        return;
    if( import_member() < 0 )
        return;
    if( import_catom() < 0 )
        return;
    if( import_event() < 0 )
        return;
    if( import_signal() < 0 )
        return;
    Py_INCREF( &MemberChange_Type );
    Py_INCREF( &Member_Type );
    Py_INCREF( &CAtom_Type );
    Py_INCREF( &Event_Type );
    Py_INCREF( &Signal_Type );
    Py_INCREF( _py_null );
    PyModule_AddObject( mod, "MemberChange", reinterpret_cast<PyObject*>( &MemberChange_Type ) );
    PyModule_AddObject( mod, "Member", reinterpret_cast<PyObject*>( &Member_Type ) );
    PyModule_AddObject( mod, "Event", reinterpret_cast<PyObject*>( &Event_Type ) );
    PyModule_AddObject( mod, "Signal", reinterpret_cast<PyObject*>( &Signal_Type ) );
    PyModule_AddObject( mod, "CAtom", reinterpret_cast<PyObject*>( &CAtom_Type ) );
    PyModule_AddObject( mod, "null", _py_null );
    PyModule_AddIntConstant( mod, "NO_VALIDATE", NoValidate );
    PyModule_AddIntConstant( mod, "VALIDATE_READ_ONLY", ValidateReadOnly );
    PyModule_AddIntConstant( mod, "VALIDATE_CONSTANT", ValidateConstant );
    PyModule_AddIntConstant( mod, "VALIDATE_BOOL", ValidateBool );
    PyModule_AddIntConstant( mod, "VALIDATE_INT", ValidateInt );
    PyModule_AddIntConstant( mod, "VALIDATE_LONG", ValidateLong );
    PyModule_AddIntConstant( mod, "VALIDATE_FLOAT", ValidateFloat );
    PyModule_AddIntConstant( mod, "VALIDATE_STR", ValidateStr );
    PyModule_AddIntConstant( mod, "VALIDATE_UNICODE", ValidateUnicode );
    PyModule_AddIntConstant( mod, "VALIDATE_UNICODE_PROMOTE", ValidateUnicodePromote );
    PyModule_AddIntConstant( mod, "VALIDATE_TUPLE", ValidateTuple );
    PyModule_AddIntConstant( mod, "VALIDATE_LIST", ValidateList );
    PyModule_AddIntConstant( mod, "VALIDATE_DICT", ValidateDict );
    PyModule_AddIntConstant( mod, "VALIDATE_INSTANCE", ValidateInstance );
    PyModule_AddIntConstant( mod, "VALIDATE_TYPED", ValidateTyped );
    PyModule_AddIntConstant( mod, "VALIDATE_ENUM", ValidateEnum );
    PyModule_AddIntConstant( mod, "VALIDATE_CALLABLE", ValidateCallable );
    PyModule_AddIntConstant( mod, "VALIDATE_OWNER_METHOD", ValidateOwnerMethod );
    PyModule_AddIntConstant( mod, "USER_VALIDATE", UserValidate );
    PyModule_AddIntConstant( mod, "DEFAULT_VALUE", DefaultValue );
    PyModule_AddIntConstant( mod, "DEFAULT_FACTORY", DefaultFactory );
    PyModule_AddIntConstant( mod, "DEFAULT_OWNER_METHOD", DefaultOwnerMethod );
    PyModule_AddIntConstant( mod, "USER_DEFAULT", UserDefault );
}

} // extern C

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "thingtypemanager.h"
#include "thingtype.h"

#include <framework/core/filestream.h>
#include <framework/core/binarytree.h>

ItemType::ItemType()
{
    m_category = ItemCategoryInvalid;
}

void ItemType::unserialize(const BinaryTreePtr& node)
{
    m_null = false;

    m_category = (ItemCategory)node->getU8();

    node->getU32(); // flags

    static uint16 lastId = 99;
    while(node->canRead()) {
        uint8 attr = node->getU8();
        if(attr == 0 || attr == 0xFF)
            break;

        uint16 len = node->getU16();
        switch(attr) {
            case ItemTypeAttrServerId: {
                uint16 serverId = node->getU16();
                if(serverId > 20000 && serverId < 20100) {
                    serverId -= 20000;
                } else if(lastId > 99 && lastId != serverId - 1) {
                    static ItemType nullType;
                    while(lastId != serverId - 1) {
                        nullType.setServerId(lastId++);
                        g_things.addItemType(ItemTypePtr(&nullType));
                    }
                }
                setServerId(serverId);
                lastId = serverId;
                break;
            }
            case ItemTypeAttrClientId: {
                setClientId(node->getU16());
                break;
            }
            case ItemTypeAttrName: {
                setName(node->getString(len));
                break;
            }
            default:
                node->skip(len); // skip attribute
                break;
        }
    }
}
<commit_msg>revert last change (better fix)<commit_after>/*
 * Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "thingtypemanager.h"
#include "thingtype.h"

#include <framework/core/filestream.h>
#include <framework/core/binarytree.h>

ItemType::ItemType()
{
    m_category = ItemCategoryInvalid;
}

void ItemType::unserialize(const BinaryTreePtr& node)
{
    m_null = false;

    m_category = (ItemCategory)node->getU8();

    node->getU32(); // flags

    static uint16 lastId = 99;
    while(node->canRead()) {
        uint8 attr = node->getU8();
        if(attr == 0 || attr == 0xFF)
            break;

        uint16 len = node->getU16();
        switch(attr) {
            case ItemTypeAttrServerId: {
                uint16 serverId = node->getU16();
                if(serverId > 20000 && serverId < 20100) {
                    serverId -= 20000;
                } else if(lastId > 99 && lastId != serverId - 1) {

                    while(lastId != serverId - 1) {
                        ItemTypePtr tmp(new ItemType);
                        tmp->setServerId(lastId++);
                        g_things.addItemType(tmp);
                    }
                }
                setServerId(serverId);
                lastId = serverId;
                break;
            }
            case ItemTypeAttrClientId: {
                setClientId(node->getU16());
                break;
            }
            case ItemTypeAttrName: {
                setName(node->getString(len));
                break;
            }
            default:
                node->skip(len); // skip attribute
                break;
        }
    }
}
<|endoftext|>


<commit_before>#include "Mesh.hxx"
#include "../sdp_read.hxx"
#include "../sdp_solve.hxx"

#include "../ostream_vector.hxx"

#include <boost/date_time/posix_time/posix_time.hpp>

// We convert the optimization problem into a regular linear
// programming problem.
//
// 1) Each polynomial in Block::polys adds two variables.  The
// weights of those polynomials are unbounded, while linear
// programming requires a strictly positive variable.  So we
// substitute W_n = w_n+ - w_n+, where both w_n+ and w_n- are
// strictly positive.  All blocks should have the same number of
// polynomials, so we only need to look at the first one.
//
// 2) Each constraint adds one 'slack' variable s_n.  There is one
// constraint per coordinate 'x', with each block having multiple,
// separate coordinates.
//
// 3) One more global variable delta, which gives the linear
// program something to minimize.
//
// This turns the problem
//
//   A_0 . W > 0
//   A_1 . W > 0
//   ...
//
// into
//
//   min delta
//
// where
//
//   A_0 . (w_+ - w_-) + delta - s_0 = 0
//   A_1 . (w_+ - w_-) + delta - s_1 = 0
//   ...
//   w_n+, w_n-, s_n, delta >= 0
//
// There is a constraint for every point that is sampled.  At the
// beginning, we sample the min and max for each block, so there are
// 2*num_blocks constraints.  For the single correlator example, there
// is an additional constraint on the first block at x=0.  In general
//
// => num_rows == num_constraints
// => num_columns == 2*num_weights + num_constraints + 1

std::vector<El::BigFloat>
load_vector(const boost::filesystem::path &vector_path);
// bool is_feasible(const Functional &functional);

std::vector<El::BigFloat>
compute_optimal(const std::vector<Positive_Matrix_With_Prefactor> &matrices,
                const std::vector<El::BigFloat> &objectives,
                const std::vector<El::BigFloat> &normalization,
                const SDP_Solver_Parameters &parameters);

int main(int argc, char **argv)
{
  El::Environment env(argc, argv);
  SDP_Solver_Parameters parameters(argc, argv);
  if(!parameters.is_valid())
    {
      return 0;
    }
  if(parameters.verbosity >= Verbosity::regular && El::mpi::Rank() == 0)
    {
      std::cout << "Outer_Limits started at "
                << boost::posix_time::second_clock::local_time() << '\n'
                << parameters << '\n'
                << std::flush;
    }

  const int64_t precision(parameters.precision);
  El::gmp::SetPrecision(precision);
  // El::gmp wants base-2 bits, but boost::multiprecision wants
  // base-10 digits.
  Boost_Float::default_precision(precision * log(2) / log(10));

  // {
  //   Functional functional("test/single_corr_polys",
  //                         "test/single_corr_prefactor",
  //                         "test/single_corr_poles");
  //   const bool is_single_corr_feasible(is_feasible(functional));
  //   std::cout << "feasible: " << std::boolalpha << is_single_corr_feasible
  //             << "\n";
  // }
  {
    std::vector<El::BigFloat> objectives, normalization;
    std::vector<Positive_Matrix_With_Prefactor> matrices;
    // read_input("outer_2x2_small.nsv", objectives, normalization, matrices);
    // read_input("outer_2x2.nsv", objectives, normalization, matrices);
    // read_input("test/spectrum_test.json", objectives, normalization, matrices);
    // read_input("test/toy_damped_duplicate.json", objectives, normalization, matrices);
    // read_input("test/toy_damped.json", objectives, normalization, matrices);
    read_input("test/toy_damped_3.json", objectives, normalization, matrices);

    std::vector<El::BigFloat> weights(
      compute_optimal(matrices, objectives, normalization, parameters));
    El::BigFloat optimal(0);
    for(size_t index(0); index < objectives.size(); ++index)
      {
        optimal += objectives[index] * weights[index];
      }
    if(El::mpi::Rank() == 0)
      {
        std::cout.precision(precision / 3.3);
        std::cout << "optimal: " << optimal << " " << weights << "\n";
      }
  }
  // {
  //   Functional functional("test/toy_polys", "test/toy_prefactor");
  //   std::vector<El::BigFloat> objective(load_vector("test/toy_objective"));
  //   std::vector<El::BigFloat> normalization(
  //     load_vector("test/toy_normalization"));
  //   std::vector<El::BigFloat> weights(
  //     compute_optimal(functional, normalization, objective));
  //   El::BigFloat optimal(0);
  //   for(size_t index(0); index < objective.size(); ++index)
  //     {
  //       optimal += objective[index] * weights[index];
  //     }
  //   std::cout.precision(precision / 3.3);
  //   std::cout << "optimal: " << optimal << " " << weights << "\n";
  // }
}
<commit_msg>Set precision before printing out precision<commit_after>#include "Mesh.hxx"
#include "../sdp_read.hxx"
#include "../sdp_solve.hxx"

#include "../ostream_vector.hxx"

#include <boost/date_time/posix_time/posix_time.hpp>

// We convert the optimization problem into a regular linear
// programming problem.
//
// 1) Each polynomial in Block::polys adds two variables.  The
// weights of those polynomials are unbounded, while linear
// programming requires a strictly positive variable.  So we
// substitute W_n = w_n+ - w_n+, where both w_n+ and w_n- are
// strictly positive.  All blocks should have the same number of
// polynomials, so we only need to look at the first one.
//
// 2) Each constraint adds one 'slack' variable s_n.  There is one
// constraint per coordinate 'x', with each block having multiple,
// separate coordinates.
//
// 3) One more global variable delta, which gives the linear
// program something to minimize.
//
// This turns the problem
//
//   A_0 . W > 0
//   A_1 . W > 0
//   ...
//
// into
//
//   min delta
//
// where
//
//   A_0 . (w_+ - w_-) + delta - s_0 = 0
//   A_1 . (w_+ - w_-) + delta - s_1 = 0
//   ...
//   w_n+, w_n-, s_n, delta >= 0
//
// There is a constraint for every point that is sampled.  At the
// beginning, we sample the min and max for each block, so there are
// 2*num_blocks constraints.  For the single correlator example, there
// is an additional constraint on the first block at x=0.  In general
//
// => num_rows == num_constraints
// => num_columns == 2*num_weights + num_constraints + 1

std::vector<El::BigFloat>
load_vector(const boost::filesystem::path &vector_path);
// bool is_feasible(const Functional &functional);

std::vector<El::BigFloat>
compute_optimal(const std::vector<Positive_Matrix_With_Prefactor> &matrices,
                const std::vector<El::BigFloat> &objectives,
                const std::vector<El::BigFloat> &normalization,
                const SDP_Solver_Parameters &parameters);

int main(int argc, char **argv)
{
  El::Environment env(argc, argv);
  SDP_Solver_Parameters parameters(argc, argv);
  if(!parameters.is_valid())
    {
      return 0;
    }

  const int64_t precision(parameters.precision);
  El::gmp::SetPrecision(precision);
  // El::gmp wants base-2 bits, but boost::multiprecision wants
  // base-10 digits.
  Boost_Float::default_precision(precision * log(2) / log(10));

  if(parameters.verbosity >= Verbosity::regular && El::mpi::Rank() == 0)
    {
      std::cout << "Outer_Limits started at "
                << boost::posix_time::second_clock::local_time() << '\n'
                << parameters << '\n'
                << std::flush;
    }

  // {
  //   Functional functional("test/single_corr_polys",
  //                         "test/single_corr_prefactor",
  //                         "test/single_corr_poles");
  //   const bool is_single_corr_feasible(is_feasible(functional));
  //   std::cout << "feasible: " << std::boolalpha << is_single_corr_feasible
  //             << "\n";
  // }
  {
    std::vector<El::BigFloat> objectives, normalization;
    std::vector<Positive_Matrix_With_Prefactor> matrices;
    // read_input("outer_2x2_small.nsv", objectives, normalization, matrices);
    // read_input("outer_2x2.nsv", objectives, normalization, matrices);
    // read_input("test/spectrum_test.json", objectives, normalization, matrices);
    // read_input("test/toy_damped_duplicate.json", objectives, normalization, matrices);
    // read_input("test/toy_damped.json", objectives, normalization, matrices);
    read_input("test/toy_damped_3.json", objectives, normalization, matrices);

    std::vector<El::BigFloat> weights(
      compute_optimal(matrices, objectives, normalization, parameters));
    El::BigFloat optimal(0);
    for(size_t index(0); index < objectives.size(); ++index)
      {
        optimal += objectives[index] * weights[index];
      }
    if(El::mpi::Rank() == 0)
      {
        std::cout.precision(precision / 3.3);
        std::cout << "optimal: " << optimal << " " << weights << "\n";
      }
  }
  // {
  //   Functional functional("test/toy_polys", "test/toy_prefactor");
  //   std::vector<El::BigFloat> objective(load_vector("test/toy_objective"));
  //   std::vector<El::BigFloat> normalization(
  //     load_vector("test/toy_normalization"));
  //   std::vector<El::BigFloat> weights(
  //     compute_optimal(functional, normalization, objective));
  //   El::BigFloat optimal(0);
  //   for(size_t index(0); index < objective.size(); ++index)
  //     {
  //       optimal += objective[index] * weights[index];
  //     }
  //   std::cout.precision(precision / 3.3);
  //   std::cout << "optimal: " << optimal << " " << weights << "\n";
  // }
}
<|endoftext|>


<commit_before>#include "output_hls.h"
#include <mist/defines.h>
#include <mist/http_parser.h>
#include <mist/stream.h>
#include <unistd.h>

namespace Mist {
  ///\brief Builds an index file for HTTP Live streaming.
  ///\return The index file for HTTP Live Streaming.
  std::string OutHLS::liveIndex(){
    std::stringstream result;
    result << "#EXTM3U\r\n";
    int audioId = -1;
    std::string audioName;
    for (std::map<int,DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++){
      if (it->second.codec == "AAC"){
        audioId = it->first;
        audioName = it->second.getIdentifier();
        break;
      }
    }
    for (std::map<int,DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++){
      if (it->second.codec == "H264"){
        int bWidth = it->second.bps * 2;
        if (audioId != -1){
          bWidth += myMeta.tracks[audioId].bps * 2;
        }
        result << "#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=" << bWidth * 10 << "\r\n";
        result << it->first;
        if (audioId != -1){
          result << "_" << audioId;
        }
        result << "/index.m3u8\r\n";
      }
    }
#if DEBUG >= 8
    std::cerr << "Sending this index:" << std::endl << result.str() << std::endl;
#endif
    return result.str();
  }

  std::string OutHLS::liveIndex(int tid){
    updateMeta();
    std::stringstream result;
    //parse single track
    int longestFragment = 0;
    if (!myMeta.tracks[tid].fragments.size()){
      DEBUG_MSG(DLVL_FAIL, "liveIndex called with track %d, which has no fragments!", tid);
      return "";
    }
    for (std::deque<DTSC::Fragment>::iterator it = myMeta.tracks[tid].fragments.begin(); (it + 1) != myMeta.tracks[tid].fragments.end(); it++){
      if (it->getDuration() > longestFragment){
        longestFragment = it->getDuration();
      }
    }
    result << "#EXTM3U\r\n"
        "#EXT-X-TARGETDURATION:" << (longestFragment / 1000) + 1 << "\r\n";
    if (myMeta.live && myMeta.tracks[tid].fragments.size() > 2){
      result << "#EXT-X-MEDIA-SEQUENCE:" << myMeta.tracks[tid].missedFrags+1 << "\r\n";
    }else{
      result << "#EXT-X-MEDIA-SEQUENCE:" << myMeta.tracks[tid].missedFrags << "\r\n";
    }
    for (std::deque<DTSC::Fragment>::iterator it = myMeta.tracks[tid].fragments.begin(); it != myMeta.tracks[tid].fragments.end(); it++){
      if (myMeta.live && myMeta.tracks[tid].fragments.size() > 2 && it == myMeta.tracks[tid].fragments.begin()){
        //skip the first fragment if live and there are more than 2 fragments.
        continue;
      }
      long long int starttime = myMeta.tracks[tid].getKey(it->getNumber()).getTime();

      if (it != (myMeta.tracks[tid].fragments.end() - 1)){
        result << "#EXTINF:" << ((it->getDuration() + 500) / 1000) << ", no desc\r\n" << starttime << "_" << it->getDuration() + starttime << ".ts\r\n";
      } else {
        //only print the last segment when VoD
        if (myMeta.vod){
          result << "#EXTINF:" << ((myMeta.tracks[tid].lastms-starttime + 500) / 1000) << ", no desc\r\n" << starttime << "_" << myMeta.tracks[tid].lastms << ".ts\r\n";
        }
      }
    }
    if ( !myMeta.live){
      result << "#EXT-X-ENDLIST\r\n";
    }
#if DEBUG >= 8
    std::cerr << "Sending this index:" << std::endl << result.str() << std::endl;
#endif
    return result.str();
  } //liveIndex

  OutHLS::OutHLS(Socket::Connection & conn) : Output(conn) {
    haveAvcc = false;
    myConn.setHost(config->getString("ip"));
    streamName = config->getString("streamname");
  }

  OutHLS::~OutHLS() {}

  void OutHLS::onFail(){
    HTTP_S.Clean(); //make sure no parts of old requests are left in any buffers
    HTTP_S.SetBody("Stream not found. Sorry, we tried.");
    HTTP_S.SendResponse("404", "Stream not found", myConn);
    Output::onFail();
  }

  void OutHLS::init(Util::Config * cfg){
    Output::init(cfg);
    capa["name"] = "HLS";
    capa["desc"] = "Enables HTTP protocol Apple-specific streaming (also known as HLS).";
    capa["deps"] = "HTTP";
    capa["url_rel"] = "/hls/$/index.m3u8";
    capa["url_prefix"] = "/hls/$/";
    capa["socket"] = "http_hls";
    capa["codecs"][0u][0u].append("H264");
    capa["codecs"][0u][1u].append("AAC");
    capa["methods"][0u]["handler"] = "http";
    capa["methods"][0u]["type"] = "html5/application/vnd.apple.mpegurl";
    capa["methods"][0u]["priority"] = 9ll;
    cfg->addBasicConnectorOptions(capa);
    config = cfg;
  }

  ///this function generates the PMT packet
  std::string OutHLS::createPMT(){
    TS::ProgramMappingTable PMT;
    PMT.PID(4096);
    PMT.setTableId(2);
    PMT.setSectionLength(0xB017);
    PMT.setProgramNumber(1);
    PMT.setVersionNumber(0);
    PMT.setCurrentNextIndicator(0);
    PMT.setSectionNumber(0);
    PMT.setLastSectionNumber(0);
    PMT.setPCRPID(0x100 + (*(selectedTracks.begin())) - 1);
    PMT.setProgramInfoLength(0);
    short id = 0;
    //for all selected tracks
    for (std::set<long unsigned int>::iterator it = selectedTracks.begin(); it != selectedTracks.end(); it++){
      if (myMeta.tracks[*it].codec == "H264"){
        PMT.setStreamType(0x1B,id);
      }else if (myMeta.tracks[*it].codec == "AAC"){
        PMT.setStreamType(0x0F,id);
      }else if (myMeta.tracks[*it].codec == "MP3"){
        PMT.setStreamType(0x03,id);
      }
      PMT.setElementaryPID(0x100 + (*it) - 1, id);
      PMT.setESInfoLength(0,id);
      id++;
    }
    PMT.calcCRC();
    return PMT.getStrBuf();
  }

  void OutHLS::fillPacket(bool & first, const char * data, size_t dataLen, char & ContCounter){

    if (!PackData.BytesFree()){
      HTTP_S.Chunkify(PackData.ToString(), 188, myConn);
      PacketNumber ++;
      PackData.Clear();
      if (PacketNumber % 42 == 0){
        HTTP_S.Chunkify(TS::PAT, 188, myConn);
        std::string PMT = createPMT();
        HTTP_S.Chunkify(PMT, myConn);
        PacketNumber += 2;
      }
    }

    if (!dataLen){return;}

    if (PackData.BytesFree() == 184){
      PackData.PID(0x100 - 1 + currentPacket.getTrackId());
      PackData.ContinuityCounter(ContCounter++);
      if (first){
        PackData.UnitStart(1);
        if (currentPacket.getInt("keyframe")){
          PackData.RandomAccess(1);
          PackData.PCR(currentPacket.getTime() * 27000);
        }
        first = false;
      }

    }

    int tmp = PackData.FillFree(data, dataLen);
    if (tmp != dataLen){
      fillPacket(first, data+tmp, dataLen-tmp, ContCounter);
    }

  }

  void OutHLS::sendNext(){
    bool first = true;
    char * ContCounter = 0;
    char * dataPointer = 0;
    unsigned int dataLen = 0;
    currentPacket.getString("data", dataPointer, dataLen); //data

    if (currentPacket.getTime() >= until){
      DEBUG_MSG(DLVL_DEVEL, "(%d) Done sending fragment", getpid() );
      stop();
      wantRequest = true;
      HTTP_S.Chunkify("", 0, myConn);
      HTTP_S.Clean();
      return;
    }

    std::string bs;
    //prepare bufferstring
    if (myMeta.tracks[currentPacket.getTrackId()].type == "video"){
      bs = TS::Packet::getPESVideoLeadIn(0ul, currentPacket.getTime() * 90);
      fillPacket(first, bs.data(), bs.size(), VideoCounter);

      if (currentPacket.getInt("keyframe")){
        if (!haveAvcc){
          avccbox.setPayload(myMeta.tracks[currentPacket.getTrackId()].init);
          haveAvcc = true;
        }
        bs = avccbox.asAnnexB();
        fillPacket(first, bs.data(), bs.size(), VideoCounter);
      }

      unsigned int i = 0;
      while (i + 4 < (unsigned int)dataLen){
        unsigned int ThisNaluSize = (dataPointer[i] << 24) + (dataPointer[i+1] << 16) + (dataPointer[i+2] << 8) + dataPointer[i+3];
        if (ThisNaluSize + i + 4 > (unsigned int)dataLen){
          DEBUG_MSG(DLVL_WARN, "Too big NALU detected (%u > %d) - skipping!", ThisNaluSize + i + 4, dataLen);
          break;
        }
        fillPacket(first, "\000\000\000\001",4, VideoCounter);
        fillPacket(first, dataPointer+i+4,ThisNaluSize, VideoCounter);
        i += ThisNaluSize+4;
      }
      if (PackData.BytesFree() < 184){
        PackData.AddStuffing();
        fillPacket(first, 0, 0, VideoCounter);
      }
    }else if (myMeta.tracks[currentPacket.getTrackId()].type == "audio"){
      if (AppleCompat){
        bs = TS::Packet::getPESAudioLeadIn(7+dataLen, lastVid);
      }else{
        bs = TS::Packet::getPESAudioLeadIn(7+dataLen, currentPacket.getTime() * 90);
      }
      fillPacket(first, bs.data(), bs.size(), AudioCounter);
      bs = TS::GetAudioHeader(dataLen, myMeta.tracks[currentPacket.getTrackId()].init);
      fillPacket(first, bs.data(), bs.size(), AudioCounter);
      ContCounter = &AudioCounter;
      fillPacket(first, dataPointer,dataLen, AudioCounter);
      if (PackData.BytesFree() < 184){
        PackData.AddStuffing();
        fillPacket(first, 0, 0, AudioCounter);
      }
    }

  }

  int OutHLS::canSeekms(unsigned int ms){
    //no tracks? Frame too new by definition.
    if ( !myMeta.tracks.size()){
      return 1;
    }
    //loop trough all the tracks
    for (std::map<int,DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++){
      //return "too late" if one track is past this point
      if (ms < it->second.firstms){
        return -1;
      }
      //return "too early" if one track is not yet at this point
      if (ms > it->second.lastms){
        return 1;
      }
    }
    return 0;
  }

  void OutHLS::onRequest(){
    while (HTTP_R.Read(myConn)){
      DEBUG_MSG(DLVL_DEVEL, "Received request: %s", HTTP_R.getUrl().c_str());
      AppleCompat = (HTTP_R.GetHeader("User-Agent").find("Apple") != std::string::npos);
      initialize();
      if (HTTP_R.url.find(".m3u") == std::string::npos){
        std::string tmpStr = HTTP_R.getUrl().substr(5+streamName.size());
        long long unsigned int from;
        if (sscanf(tmpStr.c_str(), "/%u_%u/%llu_%llu.ts", &vidTrack, &audTrack, &from, &until) != 4){
          if (sscanf(tmpStr.c_str(), "/%u/%llu_%llu.ts", &vidTrack, &from, &until) != 3){
            DEBUG_MSG(DLVL_MEDIUM, "Could not parse URL: %s", HTTP_R.getUrl().c_str());
            HTTP_S.Clean();
            HTTP_S.SetBody("The HLS URL wasn't understood - what did you want, exactly?\n");
            myConn.SendNow(HTTP_S.BuildResponse("404", "URL mismatch"));
            HTTP_R.Clean(); //clean for any possible next requests
            continue;
          }else{
            selectedTracks.clear();
            selectedTracks.insert(vidTrack);
          }
        }else{
          selectedTracks.clear();
          selectedTracks.insert(vidTrack);
          selectedTracks.insert(audTrack);
        }

        if (myMeta.live){
          /// \todo Detection of out-of-range parts.
          int seekable = canSeekms(from);
          if (seekable < 0){
            HTTP_S.Clean();
            HTTP_S.SetBody("The requested fragment is no longer kept in memory on the server and cannot be served.\n");
            myConn.SendNow(HTTP_S.BuildResponse("412", "Fragment out of range"));
            HTTP_R.Clean(); //clean for any possible next requests
            DEBUG_MSG(DLVL_WARN, "Fragment @ %llu too old", from);
            continue;
          }
          if (seekable > 0){
            HTTP_S.Clean();
            HTTP_S.SetBody("Proxy, re-request this in a second or two.\n");
            myConn.SendNow(HTTP_S.BuildResponse("208", "Ask again later"));
            HTTP_R.Clean(); //clean for any possible next requests
            DEBUG_MSG(DLVL_WARN, "Fragment @ %llu not available yet", from);
            continue;
          }
        }

        seek(from);
        lastVid = from * 90;

        HTTP_S.Clean();
        HTTP_S.SetHeader("Content-Type", "video/mp2t");
        HTTP_S.StartResponse(HTTP_R, myConn);
        PacketNumber = 0;
        parseData = true;
        wantRequest = false;
      }else{
        initialize();
        std::string request = HTTP_R.url.substr(HTTP_R.url.find("/", 5) + 1);
        HTTP_S.Clean();
        if (HTTP_R.url.find(".m3u8") != std::string::npos){
          HTTP_S.SetHeader("Content-Type", "audio/x-mpegurl");
        }else{
          HTTP_S.SetHeader("Content-Type", "audio/mpegurl");
        }
        HTTP_S.SetHeader("Cache-Control", "no-cache");
        std::string manifest;
        if (request.find("/") == std::string::npos){
          manifest = liveIndex();
        }else{
          int selectId = atoi(request.substr(0,request.find("/")).c_str());
          manifest = liveIndex(selectId);
        }
        HTTP_S.SetBody(manifest);
        HTTP_S.SendResponse("200", "OK", myConn);
      }
      HTTP_R.Clean(); //clean for any possible next requests
    }
  }
}
<commit_msg>Added ability to generate crossdomain.xml file to HLS output.<commit_after>#include "output_hls.h"
#include <mist/defines.h>
#include <mist/http_parser.h>
#include <mist/stream.h>
#include <unistd.h>

namespace Mist {
  ///\brief Builds an index file for HTTP Live streaming.
  ///\return The index file for HTTP Live Streaming.
  std::string OutHLS::liveIndex(){
    std::stringstream result;
    result << "#EXTM3U\r\n";
    int audioId = -1;
    std::string audioName;
    for (std::map<int,DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++){
      if (it->second.codec == "AAC"){
        audioId = it->first;
        audioName = it->second.getIdentifier();
        break;
      }
    }
    for (std::map<int,DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++){
      if (it->second.codec == "H264"){
        int bWidth = it->second.bps * 2;
        if (audioId != -1){
          bWidth += myMeta.tracks[audioId].bps * 2;
        }
        result << "#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=" << bWidth * 10 << "\r\n";
        result << it->first;
        if (audioId != -1){
          result << "_" << audioId;
        }
        result << "/index.m3u8\r\n";
      }
    }
#if DEBUG >= 8
    std::cerr << "Sending this index:" << std::endl << result.str() << std::endl;
#endif
    return result.str();
  }

  std::string OutHLS::liveIndex(int tid){
    updateMeta();
    std::stringstream result;
    //parse single track
    int longestFragment = 0;
    if (!myMeta.tracks[tid].fragments.size()){
      DEBUG_MSG(DLVL_FAIL, "liveIndex called with track %d, which has no fragments!", tid);
      return "";
    }
    for (std::deque<DTSC::Fragment>::iterator it = myMeta.tracks[tid].fragments.begin(); (it + 1) != myMeta.tracks[tid].fragments.end(); it++){
      if (it->getDuration() > longestFragment){
        longestFragment = it->getDuration();
      }
    }
    result << "#EXTM3U\r\n"
        "#EXT-X-TARGETDURATION:" << (longestFragment / 1000) + 1 << "\r\n";
    if (myMeta.live && myMeta.tracks[tid].fragments.size() > 2){
      result << "#EXT-X-MEDIA-SEQUENCE:" << myMeta.tracks[tid].missedFrags+1 << "\r\n";
    }else{
      result << "#EXT-X-MEDIA-SEQUENCE:" << myMeta.tracks[tid].missedFrags << "\r\n";
    }
    for (std::deque<DTSC::Fragment>::iterator it = myMeta.tracks[tid].fragments.begin(); it != myMeta.tracks[tid].fragments.end(); it++){
      if (myMeta.live && myMeta.tracks[tid].fragments.size() > 2 && it == myMeta.tracks[tid].fragments.begin()){
        //skip the first fragment if live and there are more than 2 fragments.
        continue;
      }
      long long int starttime = myMeta.tracks[tid].getKey(it->getNumber()).getTime();

      if (it != (myMeta.tracks[tid].fragments.end() - 1)){
        result << "#EXTINF:" << ((it->getDuration() + 500) / 1000) << ", no desc\r\n" << starttime << "_" << it->getDuration() + starttime << ".ts\r\n";
      } else {
        //only print the last segment when VoD
        if (myMeta.vod){
          result << "#EXTINF:" << ((myMeta.tracks[tid].lastms-starttime + 500) / 1000) << ", no desc\r\n" << starttime << "_" << myMeta.tracks[tid].lastms << ".ts\r\n";
        }
      }
    }
    if ( !myMeta.live){
      result << "#EXT-X-ENDLIST\r\n";
    }
#if DEBUG >= 8
    std::cerr << "Sending this index:" << std::endl << result.str() << std::endl;
#endif
    return result.str();
  } //liveIndex

  OutHLS::OutHLS(Socket::Connection & conn) : Output(conn) {
    haveAvcc = false;
    myConn.setHost(config->getString("ip"));
    streamName = config->getString("streamname");
  }

  OutHLS::~OutHLS() {}

  void OutHLS::onFail(){
    HTTP_S.Clean(); //make sure no parts of old requests are left in any buffers
    HTTP_S.SetBody("Stream not found. Sorry, we tried.");
    HTTP_S.SendResponse("404", "Stream not found", myConn);
    Output::onFail();
  }

  void OutHLS::init(Util::Config * cfg){
    Output::init(cfg);
    capa["name"] = "HLS";
    capa["desc"] = "Enables HTTP protocol Apple-specific streaming (also known as HLS).";
    capa["deps"] = "HTTP";
    capa["url_rel"] = "/hls/$/index.m3u8";
    capa["url_prefix"] = "/hls/$/";
    capa["socket"] = "http_hls";
    capa["codecs"][0u][0u].append("H264");
    capa["codecs"][0u][1u].append("AAC");
    capa["methods"][0u]["handler"] = "http";
    capa["methods"][0u]["type"] = "html5/application/vnd.apple.mpegurl";
    capa["methods"][0u]["priority"] = 9ll;
    cfg->addBasicConnectorOptions(capa);
    config = cfg;
  }

  ///this function generates the PMT packet
  std::string OutHLS::createPMT(){
    TS::ProgramMappingTable PMT;
    PMT.PID(4096);
    PMT.setTableId(2);
    PMT.setSectionLength(0xB017);
    PMT.setProgramNumber(1);
    PMT.setVersionNumber(0);
    PMT.setCurrentNextIndicator(0);
    PMT.setSectionNumber(0);
    PMT.setLastSectionNumber(0);
    PMT.setPCRPID(0x100 + (*(selectedTracks.begin())) - 1);
    PMT.setProgramInfoLength(0);
    short id = 0;
    //for all selected tracks
    for (std::set<long unsigned int>::iterator it = selectedTracks.begin(); it != selectedTracks.end(); it++){
      if (myMeta.tracks[*it].codec == "H264"){
        PMT.setStreamType(0x1B,id);
      }else if (myMeta.tracks[*it].codec == "AAC"){
        PMT.setStreamType(0x0F,id);
      }else if (myMeta.tracks[*it].codec == "MP3"){
        PMT.setStreamType(0x03,id);
      }
      PMT.setElementaryPID(0x100 + (*it) - 1, id);
      PMT.setESInfoLength(0,id);
      id++;
    }
    PMT.calcCRC();
    return PMT.getStrBuf();
  }

  void OutHLS::fillPacket(bool & first, const char * data, size_t dataLen, char & ContCounter){

    if (!PackData.BytesFree()){
      HTTP_S.Chunkify(PackData.ToString(), 188, myConn);
      PacketNumber ++;
      PackData.Clear();
      if (PacketNumber % 42 == 0){
        HTTP_S.Chunkify(TS::PAT, 188, myConn);
        std::string PMT = createPMT();
        HTTP_S.Chunkify(PMT, myConn);
        PacketNumber += 2;
      }
    }

    if (!dataLen){return;}

    if (PackData.BytesFree() == 184){
      PackData.PID(0x100 - 1 + currentPacket.getTrackId());
      PackData.ContinuityCounter(ContCounter++);
      if (first){
        PackData.UnitStart(1);
        if (currentPacket.getInt("keyframe")){
          PackData.RandomAccess(1);
          PackData.PCR(currentPacket.getTime() * 27000);
        }
        first = false;
      }

    }

    int tmp = PackData.FillFree(data, dataLen);
    if (tmp != dataLen){
      fillPacket(first, data+tmp, dataLen-tmp, ContCounter);
    }

  }

  void OutHLS::sendNext(){
    bool first = true;
    char * ContCounter = 0;
    char * dataPointer = 0;
    unsigned int dataLen = 0;
    currentPacket.getString("data", dataPointer, dataLen); //data

    if (currentPacket.getTime() >= until){
      DEBUG_MSG(DLVL_DEVEL, "(%d) Done sending fragment", getpid() );
      stop();
      wantRequest = true;
      HTTP_S.Chunkify("", 0, myConn);
      HTTP_S.Clean();
      return;
    }

    std::string bs;
    //prepare bufferstring
    if (myMeta.tracks[currentPacket.getTrackId()].type == "video"){
      bs = TS::Packet::getPESVideoLeadIn(0ul, currentPacket.getTime() * 90);
      fillPacket(first, bs.data(), bs.size(), VideoCounter);

      if (currentPacket.getInt("keyframe")){
        if (!haveAvcc){
          avccbox.setPayload(myMeta.tracks[currentPacket.getTrackId()].init);
          haveAvcc = true;
        }
        bs = avccbox.asAnnexB();
        fillPacket(first, bs.data(), bs.size(), VideoCounter);
      }

      unsigned int i = 0;
      while (i + 4 < (unsigned int)dataLen){
        unsigned int ThisNaluSize = (dataPointer[i] << 24) + (dataPointer[i+1] << 16) + (dataPointer[i+2] << 8) + dataPointer[i+3];
        if (ThisNaluSize + i + 4 > (unsigned int)dataLen){
          DEBUG_MSG(DLVL_WARN, "Too big NALU detected (%u > %d) - skipping!", ThisNaluSize + i + 4, dataLen);
          break;
        }
        fillPacket(first, "\000\000\000\001",4, VideoCounter);
        fillPacket(first, dataPointer+i+4,ThisNaluSize, VideoCounter);
        i += ThisNaluSize+4;
      }
      if (PackData.BytesFree() < 184){
        PackData.AddStuffing();
        fillPacket(first, 0, 0, VideoCounter);
      }
    }else if (myMeta.tracks[currentPacket.getTrackId()].type == "audio"){
      if (AppleCompat){
        bs = TS::Packet::getPESAudioLeadIn(7+dataLen, lastVid);
      }else{
        bs = TS::Packet::getPESAudioLeadIn(7+dataLen, currentPacket.getTime() * 90);
      }
      fillPacket(first, bs.data(), bs.size(), AudioCounter);
      bs = TS::GetAudioHeader(dataLen, myMeta.tracks[currentPacket.getTrackId()].init);
      fillPacket(first, bs.data(), bs.size(), AudioCounter);
      ContCounter = &AudioCounter;
      fillPacket(first, dataPointer,dataLen, AudioCounter);
      if (PackData.BytesFree() < 184){
        PackData.AddStuffing();
        fillPacket(first, 0, 0, AudioCounter);
      }
    }

  }

  int OutHLS::canSeekms(unsigned int ms){
    //no tracks? Frame too new by definition.
    if ( !myMeta.tracks.size()){
      return 1;
    }
    //loop trough all the tracks
    for (std::map<int,DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++){
      //return "too late" if one track is past this point
      if (ms < it->second.firstms){
        return -1;
      }
      //return "too early" if one track is not yet at this point
      if (ms > it->second.lastms){
        return 1;
      }
    }
    return 0;
  }

  void OutHLS::onRequest(){
    while (HTTP_R.Read(myConn)){
      DEBUG_MSG(DLVL_DEVEL, "Received request: %s", HTTP_R.getUrl().c_str());

      if (HTTP_R.url == "/crossdomain.xml"){
        HTTP_S.Clean();
        HTTP_S.SetHeader("Content-Type", "text/xml");
        HTTP_S.SetHeader("Server", "mistserver/" PACKAGE_VERSION "/" + Util::Config::libver);
        HTTP_S.SetBody("<?xml version=\"1.0\"?><!DOCTYPE cross-domain-policy SYSTEM \"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd\"><cross-domain-policy><allow-access-from domain=\"*\" /><site-control permitted-cross-domain-policies=\"all\"/></cross-domain-policy>");
        HTTP_S.SendResponse("200", "OK", myConn);
        HTTP_R.Clean(); //clean for any possible next requests
        continue;
      } //crossdomain.xml

      AppleCompat = (HTTP_R.GetHeader("User-Agent").find("Apple") != std::string::npos);
      initialize();
      if (HTTP_R.url.find(".m3u") == std::string::npos){
        std::string tmpStr = HTTP_R.getUrl().substr(5+streamName.size());
        long long unsigned int from;
        if (sscanf(tmpStr.c_str(), "/%u_%u/%llu_%llu.ts", &vidTrack, &audTrack, &from, &until) != 4){
          if (sscanf(tmpStr.c_str(), "/%u/%llu_%llu.ts", &vidTrack, &from, &until) != 3){
            DEBUG_MSG(DLVL_MEDIUM, "Could not parse URL: %s", HTTP_R.getUrl().c_str());
            HTTP_S.Clean();
            HTTP_S.SetBody("The HLS URL wasn't understood - what did you want, exactly?\n");
            myConn.SendNow(HTTP_S.BuildResponse("404", "URL mismatch"));
            HTTP_R.Clean(); //clean for any possible next requests
            continue;
          }else{
            selectedTracks.clear();
            selectedTracks.insert(vidTrack);
          }
        }else{
          selectedTracks.clear();
          selectedTracks.insert(vidTrack);
          selectedTracks.insert(audTrack);
        }

        if (myMeta.live){
          /// \todo Detection of out-of-range parts.
          int seekable = canSeekms(from);
          if (seekable < 0){
            HTTP_S.Clean();
            HTTP_S.SetBody("The requested fragment is no longer kept in memory on the server and cannot be served.\n");
            myConn.SendNow(HTTP_S.BuildResponse("412", "Fragment out of range"));
            HTTP_R.Clean(); //clean for any possible next requests
            DEBUG_MSG(DLVL_WARN, "Fragment @ %llu too old", from);
            continue;
          }
          if (seekable > 0){
            HTTP_S.Clean();
            HTTP_S.SetBody("Proxy, re-request this in a second or two.\n");
            myConn.SendNow(HTTP_S.BuildResponse("208", "Ask again later"));
            HTTP_R.Clean(); //clean for any possible next requests
            DEBUG_MSG(DLVL_WARN, "Fragment @ %llu not available yet", from);
            continue;
          }
        }

        seek(from);
        lastVid = from * 90;

        HTTP_S.Clean();
        HTTP_S.SetHeader("Content-Type", "video/mp2t");
        HTTP_S.StartResponse(HTTP_R, myConn);
        PacketNumber = 0;
        parseData = true;
        wantRequest = false;
      }else{
        initialize();
        std::string request = HTTP_R.url.substr(HTTP_R.url.find("/", 5) + 1);
        HTTP_S.Clean();
        if (HTTP_R.url.find(".m3u8") != std::string::npos){
          HTTP_S.SetHeader("Content-Type", "audio/x-mpegurl");
        }else{
          HTTP_S.SetHeader("Content-Type", "audio/mpegurl");
        }
        HTTP_S.SetHeader("Cache-Control", "no-cache");
        std::string manifest;
        if (request.find("/") == std::string::npos){
          manifest = liveIndex();
        }else{
          int selectId = atoi(request.substr(0,request.find("/")).c_str());
          manifest = liveIndex(selectId);
        }
        HTTP_S.SetBody(manifest);
        HTTP_S.SendResponse("200", "OK", myConn);
      }
      HTTP_R.Clean(); //clean for any possible next requests
    }
  }
}
<|endoftext|>


<commit_before>
/* bzflag
 * Copyright (c) 1993 - 2005 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "common.h"

#ifdef HAVE_SDL
#include <stdlib.h>
#include <string>
#include "SDLMedia.h"
#include "ErrorHandler.h"

#ifdef HALF_RATE_AUDIO
static const int defaultAudioRate=11025;
#else
static const int defaultAudioRate=22050;
#endif

//
// SDLMedia
//

SDLMedia::SDLMedia() : BzfMedia()
{
  cmdFill       = 0;
  audioReady    = false;
}

double			SDLMedia::stopwatch(bool start)
{
  Uint32 currentTick = SDL_GetTicks(); //msec

  if (start) {
    stopwatchTime = currentTick;
    return 0.0;
  }
  if (currentTick >= stopwatchTime)
    return (double) (currentTick - stopwatchTime) * 0.001; // sec
  else
    //Clock is wrapped : happens after 49 days
    //Should be "wrap value" - stopwatchtime. Now approx.
    return (double) currentTick * 0.001;
}

bool			SDLMedia::openAudio()
{
  // don't re-initialize
  if (audioReady) return false;

  if (SDL_InitSubSystem(SDL_INIT_AUDIO) == -1) {
    printFatalError("Could not initialize SDL-Audio: %s.\n", SDL_GetError());
    exit(-1);
  };

  static SDL_AudioSpec desired;

  // what the frequency?
  audioOutputRate = defaultAudioRate;

  // how big a fragment to use?  we want to hold at around 1/10th of
  // a second.
  // probably SDL is using multiple buffering, make it a 3rd
  int fragmentSize = (int)(0.03f * (float)audioOutputRate);
  int n;

  n = 0;
  while ((1 << n) < fragmentSize)
    ++n;

  // samples are two bytes each so double the size
  audioBufferSize = 1 << (n + 1);

  desired.freq       = audioOutputRate;
  desired.format     = AUDIO_S16SYS;
  desired.channels   = 2;
  desired.samples    = audioBufferSize >> 1; // In stereo samples
  desired.callback   = &fillAudioWrapper;
  desired.userdata   = (void *) this;	// To handle Wrap of func

  /* Open the audio device, forcing the desired format */
  if (SDL_OpenAudio(&desired, NULL) < 0) {
    fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
    return false;
  }

  // make an output buffer
  outputBuffer  = new short[audioBufferSize];

  // ready to go
  audioReady = true;

  return true;
}

void			SDLMedia::closeAudio()
{
  // Stop Audio to avoid callback
  SDL_PauseAudio(1);

  SDL_CloseAudio();
  delete [] outputBuffer;
  outputBuffer  = 0;
  SDL_QuitSubSystem(SDL_INIT_AUDIO);
  audioReady    = false;
}

void			SDLMedia::startAudioCallback(bool (*proc)(void))
{
  userCallback = proc;

  // Stop sending silence and start calling audio callback
  SDL_PauseAudio(0);
}

void			SDLMedia::writeSoundCommand(const void* cmd, int len)
{
  if (!audioReady) return;

  SDL_LockAudio();

  // Discard command if full
  if ((cmdFill + len) < 2048) {
    memcpy(&cmdQueue[cmdFill], cmd, len);
    // We should awake audioSleep - but game become unplayable
    // using here an SDL_CondSignal(wakeCond)
    cmdFill += len;
  }

  SDL_UnlockAudio();
}

bool			SDLMedia::readSoundCommand(void* cmd, int len)
{
  bool result = false;

  if (cmdFill >= len) {
    memcpy(cmd, cmdQueue, len);
    // repack list of command waiting to be processed
    memmove(cmdQueue, &cmdQueue[len], cmdFill - len);
    cmdFill -= len;
    result = true;
  }
  return result;
}

int			SDLMedia::getAudioOutputRate() const
{
  return audioOutputRate;
}

int			SDLMedia::getAudioBufferSize() const
{
  return audioBufferSize;
}

int			SDLMedia::getAudioBufferChunkSize() const
{
  return audioBufferSize>>1;
}

void SDLMedia::fillAudio (Uint8 * stream, int len)
{
  userCallback();
  Uint8* soundBuffer	= stream;

  int transferSize = (audioBufferSize - sampleToSend) * 2;
  if (transferSize > len)
    transferSize   = len;
  // just copying into the soundBuffer is enough, SDL is looking for
  // something different from silence sample
  memcpy(soundBuffer,
	 (Uint8 *) &outputBuffer[sampleToSend],
	 transferSize);
  sampleToSend    += transferSize / 2;
  soundBuffer     += transferSize;
  len	     -= transferSize;

}

void SDLMedia::fillAudioWrapper (void * userdata, Uint8 * stream, int len)
{
  SDLMedia * me = (SDLMedia *) userdata;
  me->fillAudio(stream, len);
};

void			SDLMedia::writeAudioFrames(
				const float* samples, int numFrames)
{
  int numSamples = 2 * numFrames;
  int limit;

  while (numSamples > 0) {
    if (numSamples>audioBufferSize)
      limit=audioBufferSize;
    else
      limit=numSamples;
    for (int j = 0; j < limit; j++) {
      if (samples[j] < -32767.0)
	outputBuffer[j] = -32767;
      else
	if (samples[j] > 32767.0)
	  outputBuffer[j] = 32767;
	else
	  outputBuffer[j] = short(samples[j]);
    }

    // fill out the chunk (we never write a partial chunk)
    if (limit < audioBufferSize) {
      for (int j = limit; j < audioBufferSize; ++j)
	outputBuffer[j] = 0;
    }

    sampleToSend = 0;

    samples    += audioBufferSize;
    numSamples -= audioBufferSize;
  }
}

// Setting Audio Driver
void	SDLMedia::setDriver(std::string driverName) {
  char envAssign[256];
  std::string envVar = "SDL_AUDIODRIVER=" + driverName;
  strncpy(envAssign, envVar.c_str(), 255);
  envAssign[255]     = '\0';
  putenv(envAssign);
};

// Setting Audio Device
void	SDLMedia::setDevice(std::string deviceName) {
  char envAssign[256];
  std::string envVar = "SDL_PATH_DSP=" + deviceName;
  strncpy(envAssign, envVar.c_str(), 255);
  envAssign[255]     = '\0';
  putenv(envAssign);
};

float*	    SDLMedia::doReadSound(const std::string &filename, int &numFrames,
				  int &rate) const
{
  SDL_AudioSpec wav_spec;
  Uint32	wav_length;
  Uint8	*wav_buffer;
  int	   ret;
  SDL_AudioCVT  wav_cvt;
  int16_t      *cvt16;
  int	   i;

  float	*data = NULL;
  rate	= defaultAudioRate;
  if (SDL_LoadWAV(filename.c_str(), &wav_spec, &wav_buffer, &wav_length)) {
    /* Build AudioCVT */
    ret = SDL_BuildAudioCVT(&wav_cvt,
			    wav_spec.format, wav_spec.channels, wav_spec.freq,
			    AUDIO_S16SYS, 2, defaultAudioRate);
    /* Check that the convert was built */
    if (ret == -1) {
      printFatalError("Could not build converter for Wav file %s: %s.\n",
		      filename.c_str(), SDL_GetError());
    } else {
      /* Setup for conversion */
      wav_cvt.buf = (Uint8*)malloc(wav_length * wav_cvt.len_mult);
      wav_cvt.len = wav_length;
      memcpy(wav_cvt.buf, wav_buffer, wav_length);
      /* And now we're ready to convert */
      SDL_ConvertAudio(&wav_cvt);
      numFrames = (int)(wav_length * wav_cvt.len_ratio / 4);
      cvt16     = (int16_t *)wav_cvt.buf;
      data      = new float[numFrames * 2];
      for (i = 0; i < numFrames * 2; i++)
	data[i] = cvt16[i];
      free(wav_cvt.buf);
    }
    SDL_FreeWAV(wav_buffer);
  }
  return data;
}

void SDLMedia::audioDriver(std::string& driverName)
{
  char driver[128] = "SDL: audio not available";
  char *result = SDL_AudioDriverName(driver, sizeof(driver));
  if (result)
    driverName = driver;
  else
    driverName = "SDL: audio not available";
}

#endif //HAVE_SDL
// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8

<commit_msg>Rem: Careful writing into the environment<commit_after>
/* bzflag
 * Copyright (c) 1993 - 2005 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "common.h"

#ifdef HAVE_SDL
#include <stdlib.h>
#include <string>
#include "SDLMedia.h"
#include "ErrorHandler.h"

#ifdef HALF_RATE_AUDIO
static const int defaultAudioRate=11025;
#else
static const int defaultAudioRate=22050;
#endif

//
// SDLMedia
//

SDLMedia::SDLMedia() : BzfMedia()
{
  cmdFill       = 0;
  audioReady    = false;
}

double			SDLMedia::stopwatch(bool start)
{
  Uint32 currentTick = SDL_GetTicks(); //msec

  if (start) {
    stopwatchTime = currentTick;
    return 0.0;
  }
  if (currentTick >= stopwatchTime)
    return (double) (currentTick - stopwatchTime) * 0.001; // sec
  else
    //Clock is wrapped : happens after 49 days
    //Should be "wrap value" - stopwatchtime. Now approx.
    return (double) currentTick * 0.001;
}

bool			SDLMedia::openAudio()
{
  // don't re-initialize
  if (audioReady) return false;

  if (SDL_InitSubSystem(SDL_INIT_AUDIO) == -1) {
    printFatalError("Could not initialize SDL-Audio: %s.\n", SDL_GetError());
    exit(-1);
  };

  static SDL_AudioSpec desired;

  // what the frequency?
  audioOutputRate = defaultAudioRate;

  // how big a fragment to use?  we want to hold at around 1/10th of
  // a second.
  // probably SDL is using multiple buffering, make it a 3rd
  int fragmentSize = (int)(0.03f * (float)audioOutputRate);
  int n;

  n = 0;
  while ((1 << n) < fragmentSize)
    ++n;

  // samples are two bytes each so double the size
  audioBufferSize = 1 << (n + 1);

  desired.freq       = audioOutputRate;
  desired.format     = AUDIO_S16SYS;
  desired.channels   = 2;
  desired.samples    = audioBufferSize >> 1; // In stereo samples
  desired.callback   = &fillAudioWrapper;
  desired.userdata   = (void *) this;	// To handle Wrap of func

  /* Open the audio device, forcing the desired format */
  if (SDL_OpenAudio(&desired, NULL) < 0) {
    fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
    return false;
  }

  // make an output buffer
  outputBuffer  = new short[audioBufferSize];

  // ready to go
  audioReady = true;

  return true;
}

void			SDLMedia::closeAudio()
{
  // Stop Audio to avoid callback
  SDL_PauseAudio(1);

  SDL_CloseAudio();
  delete [] outputBuffer;
  outputBuffer  = 0;
  SDL_QuitSubSystem(SDL_INIT_AUDIO);
  audioReady    = false;
}

void			SDLMedia::startAudioCallback(bool (*proc)(void))
{
  userCallback = proc;

  // Stop sending silence and start calling audio callback
  SDL_PauseAudio(0);
}

void			SDLMedia::writeSoundCommand(const void* cmd, int len)
{
  if (!audioReady) return;

  SDL_LockAudio();

  // Discard command if full
  if ((cmdFill + len) < 2048) {
    memcpy(&cmdQueue[cmdFill], cmd, len);
    // We should awake audioSleep - but game become unplayable
    // using here an SDL_CondSignal(wakeCond)
    cmdFill += len;
  }

  SDL_UnlockAudio();
}

bool			SDLMedia::readSoundCommand(void* cmd, int len)
{
  bool result = false;

  if (cmdFill >= len) {
    memcpy(cmd, cmdQueue, len);
    // repack list of command waiting to be processed
    memmove(cmdQueue, &cmdQueue[len], cmdFill - len);
    cmdFill -= len;
    result = true;
  }
  return result;
}

int			SDLMedia::getAudioOutputRate() const
{
  return audioOutputRate;
}

int			SDLMedia::getAudioBufferSize() const
{
  return audioBufferSize;
}

int			SDLMedia::getAudioBufferChunkSize() const
{
  return audioBufferSize>>1;
}

void SDLMedia::fillAudio (Uint8 * stream, int len)
{
  userCallback();
  Uint8* soundBuffer	= stream;

  int transferSize = (audioBufferSize - sampleToSend) * 2;
  if (transferSize > len)
    transferSize   = len;
  // just copying into the soundBuffer is enough, SDL is looking for
  // something different from silence sample
  memcpy(soundBuffer,
	 (Uint8 *) &outputBuffer[sampleToSend],
	 transferSize);
  sampleToSend    += transferSize / 2;
  soundBuffer     += transferSize;
  len	     -= transferSize;

}

void SDLMedia::fillAudioWrapper (void * userdata, Uint8 * stream, int len)
{
  SDLMedia * me = (SDLMedia *) userdata;
  me->fillAudio(stream, len);
};

void			SDLMedia::writeAudioFrames(
				const float* samples, int numFrames)
{
  int numSamples = 2 * numFrames;
  int limit;

  while (numSamples > 0) {
    if (numSamples>audioBufferSize)
      limit=audioBufferSize;
    else
      limit=numSamples;
    for (int j = 0; j < limit; j++) {
      if (samples[j] < -32767.0)
	outputBuffer[j] = -32767;
      else
	if (samples[j] > 32767.0)
	  outputBuffer[j] = 32767;
	else
	  outputBuffer[j] = short(samples[j]);
    }

    // fill out the chunk (we never write a partial chunk)
    if (limit < audioBufferSize) {
      for (int j = limit; j < audioBufferSize; ++j)
	outputBuffer[j] = 0;
    }

    sampleToSend = 0;

    samples    += audioBufferSize;
    numSamples -= audioBufferSize;
  }
}

// Setting Audio Driver
void	SDLMedia::setDriver(std::string driverName) {
  static char envAssign[256];
  std::string envVar = "SDL_AUDIODRIVER=" + driverName;
  strncpy(envAssign, envVar.c_str(), 255);
  envAssign[255]     = '\0';
  putenv(envAssign);
};

// Setting Audio Device
void	SDLMedia::setDevice(std::string deviceName) {
  static char envAssign[256];
  std::string envVar = "SDL_PATH_DSP=" + deviceName;
  strncpy(envAssign, envVar.c_str(), 255);
  envAssign[255]     = '\0';
  putenv(envAssign);
};

float*	    SDLMedia::doReadSound(const std::string &filename, int &numFrames,
				  int &rate) const
{
  SDL_AudioSpec wav_spec;
  Uint32	wav_length;
  Uint8	*wav_buffer;
  int	   ret;
  SDL_AudioCVT  wav_cvt;
  int16_t      *cvt16;
  int	   i;

  float	*data = NULL;
  rate	= defaultAudioRate;
  if (SDL_LoadWAV(filename.c_str(), &wav_spec, &wav_buffer, &wav_length)) {
    /* Build AudioCVT */
    ret = SDL_BuildAudioCVT(&wav_cvt,
			    wav_spec.format, wav_spec.channels, wav_spec.freq,
			    AUDIO_S16SYS, 2, defaultAudioRate);
    /* Check that the convert was built */
    if (ret == -1) {
      printFatalError("Could not build converter for Wav file %s: %s.\n",
		      filename.c_str(), SDL_GetError());
    } else {
      /* Setup for conversion */
      wav_cvt.buf = (Uint8*)malloc(wav_length * wav_cvt.len_mult);
      wav_cvt.len = wav_length;
      memcpy(wav_cvt.buf, wav_buffer, wav_length);
      /* And now we're ready to convert */
      SDL_ConvertAudio(&wav_cvt);
      numFrames = (int)(wav_length * wav_cvt.len_ratio / 4);
      cvt16     = (int16_t *)wav_cvt.buf;
      data      = new float[numFrames * 2];
      for (i = 0; i < numFrames * 2; i++)
	data[i] = cvt16[i];
      free(wav_cvt.buf);
    }
    SDL_FreeWAV(wav_buffer);
  }
  return data;
}

void SDLMedia::audioDriver(std::string& driverName)
{
  char driver[128] = "SDL: audio not available";
  char *result = SDL_AudioDriverName(driver, sizeof(driver));
  if (result)
    driverName = driver;
  else
    driverName = "SDL: audio not available";
}

#endif //HAVE_SDL
// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8

<|endoftext|>


<commit_before>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
*/
#include <osg/ClipNode>

#include <algorithm>

using namespace osg;

ClipNode::ClipNode():
    _value(StateAttribute::ON)
{
    _stateset = new StateSet;
}

ClipNode::ClipNode(const ClipNode& cn, const CopyOp& copyop):
    Group(cn,copyop),
    _value(cn._value)
{
    for(ClipPlaneList::const_iterator itr=cn._planes.begin();
        itr!=cn._planes.end();
        ++itr)
    {
        ClipPlane* plane = dynamic_cast<ClipPlane*>(copyop(itr->get()));
        if (!plane)
            continue;
        _planes.push_back(plane);
        _stateset->setAssociatedModes(plane, _value);
    }
}

ClipNode::~ClipNode()
{
}

// Create a 6 clip planes to create a clip box.
void ClipNode::createClipBox(const BoundingBox& bb,unsigned int clipPlaneNumberBase)
{
    _planes.clear();
    if (!_stateset.valid()) _stateset = new osg::StateSet;

    _planes.push_back(new ClipPlane(clipPlaneNumberBase  ,1.0,0.0,0.0,-bb.xMin()));
    _stateset->setAssociatedModes(_planes.back().get(), _value);
    _planes.push_back(new ClipPlane(clipPlaneNumberBase+1,-1.0,0.0,0.0,bb.xMax()));
    _stateset->setAssociatedModes(_planes.back().get(), _value);

    _planes.push_back(new ClipPlane(clipPlaneNumberBase+2,0.0,1.0,0.0,-bb.yMin()));
    _stateset->setAssociatedModes(_planes.back().get(), _value);
    _planes.push_back(new ClipPlane(clipPlaneNumberBase+3,0.0,-1.0,0.0,bb.yMax()));
    _stateset->setAssociatedModes(_planes.back().get(), _value);

    _planes.push_back(new ClipPlane(clipPlaneNumberBase+4,0.0,0.0,1.0,-bb.zMin()));
    _stateset->setAssociatedModes(_planes.back().get(), _value);
    _planes.push_back(new ClipPlane(clipPlaneNumberBase+5,0.0,0.0,-1.0,bb.zMax()));
    _stateset->setAssociatedModes(_planes.back().get(), _value);
}

// Add a ClipPlane to a ClipNode. Return true if plane is added,
// return false if plane already exists in ClipNode, or clipplane is false.
bool ClipNode::addClipPlane(ClipPlane* clipplane)
{
    if (!clipplane) return false;

    if (std::find(_planes.begin(),_planes.end(),clipplane)==_planes.end())
    {
        // cliplane doesn't exist in list so add it.
        _planes.push_back(clipplane);
        if (!_stateset.valid()) _stateset = new osg::StateSet;
        _stateset->setAssociatedModes(clipplane, _value);
        return true;
    }
    else
    {
        return false;
    }
}

// Remove ClipPlane from a ClipNode. Return true if plane is removed,
// return false if plane does not exists in ClipNode.
bool ClipNode::removeClipPlane(ClipPlane* clipplane)
{
    if (!clipplane) return false;

    ClipPlaneList::iterator itr = std::find(_planes.begin(),_planes.end(),clipplane);
    if (itr!=_planes.end())
    {
        // cliplane exist in list so erase it.
        _stateset->removeAssociatedModes(clipplane);
        _planes.erase(itr);
        return true;
    }
    else
    {
        return false;
    }
}

// Remove ClipPlane, at specified index, from a ClipNode. Return true if plane is removed,
// return false if plane does not exists in ClipNode.
bool ClipNode::removeClipPlane(unsigned int pos)
{
    if (pos<_planes.size())
    {
        ClipPlaneList::iterator itr = _planes.begin();
        std::advance(itr, pos);
        _stateset->removeAssociatedModes(itr->get());
        _planes.erase(itr);
        return true;
    }
    else
    {
        return false;
    }
}

// Set the GLModes on StateSet associated with the ClipPlanes.
void ClipNode::setStateSetModes(StateSet& stateset,StateAttribute::GLModeValue value) const
{
    for(ClipPlaneList::const_iterator itr=_planes.begin();
        itr!=_planes.end();
        ++itr)
    {
        stateset.setAssociatedModes(itr->get(),value);
    }
}

void ClipNode::setLocalStateSetModes(const StateAttribute::GLModeValue value)
{
    _value = value;
    if (!_stateset) _stateset = new StateSet;
    setStateSetModes(*_stateset,value);
}

BoundingSphere ClipNode::computeBound() const
{
    return Group::computeBound();
}
<commit_msg>Removed erroneous const in method parameter<commit_after>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
*/
#include <osg/ClipNode>

#include <algorithm>

using namespace osg;

ClipNode::ClipNode():
    _value(StateAttribute::ON)
{
    _stateset = new StateSet;
}

ClipNode::ClipNode(const ClipNode& cn, const CopyOp& copyop):
    Group(cn,copyop),
    _value(cn._value)
{
    for(ClipPlaneList::const_iterator itr=cn._planes.begin();
        itr!=cn._planes.end();
        ++itr)
    {
        ClipPlane* plane = dynamic_cast<ClipPlane*>(copyop(itr->get()));
        if (!plane)
            continue;
        _planes.push_back(plane);
        _stateset->setAssociatedModes(plane, _value);
    }
}

ClipNode::~ClipNode()
{
}

// Create a 6 clip planes to create a clip box.
void ClipNode::createClipBox(const BoundingBox& bb,unsigned int clipPlaneNumberBase)
{
    _planes.clear();
    if (!_stateset.valid()) _stateset = new osg::StateSet;

    _planes.push_back(new ClipPlane(clipPlaneNumberBase  ,1.0,0.0,0.0,-bb.xMin()));
    _stateset->setAssociatedModes(_planes.back().get(), _value);
    _planes.push_back(new ClipPlane(clipPlaneNumberBase+1,-1.0,0.0,0.0,bb.xMax()));
    _stateset->setAssociatedModes(_planes.back().get(), _value);

    _planes.push_back(new ClipPlane(clipPlaneNumberBase+2,0.0,1.0,0.0,-bb.yMin()));
    _stateset->setAssociatedModes(_planes.back().get(), _value);
    _planes.push_back(new ClipPlane(clipPlaneNumberBase+3,0.0,-1.0,0.0,bb.yMax()));
    _stateset->setAssociatedModes(_planes.back().get(), _value);

    _planes.push_back(new ClipPlane(clipPlaneNumberBase+4,0.0,0.0,1.0,-bb.zMin()));
    _stateset->setAssociatedModes(_planes.back().get(), _value);
    _planes.push_back(new ClipPlane(clipPlaneNumberBase+5,0.0,0.0,-1.0,bb.zMax()));
    _stateset->setAssociatedModes(_planes.back().get(), _value);
}

// Add a ClipPlane to a ClipNode. Return true if plane is added,
// return false if plane already exists in ClipNode, or clipplane is false.
bool ClipNode::addClipPlane(ClipPlane* clipplane)
{
    if (!clipplane) return false;

    if (std::find(_planes.begin(),_planes.end(),clipplane)==_planes.end())
    {
        // cliplane doesn't exist in list so add it.
        _planes.push_back(clipplane);
        if (!_stateset.valid()) _stateset = new osg::StateSet;
        _stateset->setAssociatedModes(clipplane, _value);
        return true;
    }
    else
    {
        return false;
    }
}

// Remove ClipPlane from a ClipNode. Return true if plane is removed,
// return false if plane does not exists in ClipNode.
bool ClipNode::removeClipPlane(ClipPlane* clipplane)
{
    if (!clipplane) return false;

    ClipPlaneList::iterator itr = std::find(_planes.begin(),_planes.end(),clipplane);
    if (itr!=_planes.end())
    {
        // cliplane exist in list so erase it.
        _stateset->removeAssociatedModes(clipplane);
        _planes.erase(itr);
        return true;
    }
    else
    {
        return false;
    }
}

// Remove ClipPlane, at specified index, from a ClipNode. Return true if plane is removed,
// return false if plane does not exists in ClipNode.
bool ClipNode::removeClipPlane(unsigned int pos)
{
    if (pos<_planes.size())
    {
        ClipPlaneList::iterator itr = _planes.begin();
        std::advance(itr, pos);
        _stateset->removeAssociatedModes(itr->get());
        _planes.erase(itr);
        return true;
    }
    else
    {
        return false;
    }
}

// Set the GLModes on StateSet associated with the ClipPlanes.
void ClipNode::setStateSetModes(StateSet& stateset,StateAttribute::GLModeValue value) const
{
    for(ClipPlaneList::const_iterator itr=_planes.begin();
        itr!=_planes.end();
        ++itr)
    {
        stateset.setAssociatedModes(itr->get(),value);
    }
}

void ClipNode::setLocalStateSetModes(StateAttribute::GLModeValue value)
{
    _value = value;
    if (!_stateset) _stateset = new StateSet;
    setStateSetModes(*_stateset,value);
}

BoundingSphere ClipNode::computeBound() const
{
    return Group::computeBound();
}
<|endoftext|>