<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "BoostThreadFactory.h"
#include "Exception.h"

#include <cassert>

#include <boost/weak_ptr.hpp>
#include <boost/thread.hpp>

namespace apache { namespace thrift { namespace concurrency {

using boost::shared_ptr;
using boost::weak_ptr;

/**
 * The boost thread class.
 *
 * @version $Id:$
 */
class BoostThread: public Thread {
 public:

  enum STATE {
    uninitialized,
    starting,
    started,
    stopping,
    stopped
  };

  static void* threadMain(void* arg);

 private:
  std::auto_ptr<boost::thread> thread_;
  STATE state_;
  weak_ptr<BoostThread> self_;
  bool detached_;

 public:

  BoostThread(bool detached, shared_ptr<Runnable> runnable) :
	 state_(uninitialized),
	 detached_(detached) {
    this->Thread::runnable(runnable);
  }

  ~BoostThread() {
    if(!detached_) {
      try {
        join();
      } catch(...) {
        // We're really hosed.
      }
    }
  }

  void start() {
    if (state_ != uninitialized) {
      return;
    }

	// Create reference
    shared_ptr<BoostThread>* selfRef = new shared_ptr<BoostThread>();
    *selfRef = self_.lock();

	thread_ = std::auto_ptr<boost::thread>(new boost::thread(boost::bind(threadMain, (void*)selfRef)));

	if(detached_)
		thread_->detach();

	state_ = starting;
  }

  void join() {
    if (!detached_ && state_ != uninitialized) {
	  thread_->join();
    }
  }

  Thread::id_t getId() {
	  return thread_.get() ? thread_->get_id() : boost::thread::id();
  }

  shared_ptr<Runnable> runnable() const { return Thread::runnable(); }

  void runnable(shared_ptr<Runnable> value) { Thread::runnable(value); }

  void weakRef(shared_ptr<BoostThread> self) {
    assert(self.get() == this);
    self_ = weak_ptr<BoostThread>(self);
  }
};

void* BoostThread::threadMain(void* arg) {
  shared_ptr<BoostThread> thread = *(shared_ptr<BoostThread>*)arg;
  delete reinterpret_cast<shared_ptr<BoostThread>*>(arg);

  if (thread == NULL) {
    return (void*)0;
  }

  if (thread->state_ != starting) {
    return (void*)0;
  }

  thread->state_ = started;
  thread->runnable()->run();

  if (thread->state_ != stopping && thread->state_ != stopped) {
    thread->state_ = stopping;
  }
  return (void*)0;
}

/**
 * POSIX Thread factory implementation
 */
class BoostThreadFactory::Impl {

 private:
  bool detached_;

 public:

  Impl(bool detached) :
    detached_(detached) {}

  /**
   * Creates a new POSIX thread to run the runnable object
   *
   * @param runnable A runnable object
   */
  shared_ptr<Thread> newThread(shared_ptr<Runnable> runnable) const {
    shared_ptr<BoostThread> result = shared_ptr<BoostThread>(new BoostThread(detached_, runnable));
    result->weakRef(result);
    runnable->thread(result);
    return result;
  }

  bool isDetached() const { return detached_; }

  void setDetached(bool value) { detached_ = value; }

  Thread::id_t getCurrentThreadId() const {
	  return boost::this_thread::get_id();
  }

};

BoostThreadFactory::BoostThreadFactory(bool detached) :
  impl_(new BoostThreadFactory::Impl(detached)) {}

shared_ptr<Thread> BoostThreadFactory::newThread(shared_ptr<Runnable> runnable) const { return impl_->newThread(runnable); }

bool BoostThreadFactory::isDetached() const { return impl_->isDetached(); }

void BoostThreadFactory::setDetached(bool value) { impl_->setDetached(value); }

Thread::id_t BoostThreadFactory::getCurrentThreadId() const { return impl_->getCurrentThreadId(); }

}}} // apache::thrift::concurrency
<commit_msg>Thrift-1606:Race condition in BoostThreadFactory.cpp Client: cpp Patch: alexandre parenteau<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "BoostThreadFactory.h"
#include "Exception.h"

#include <cassert>

#include <boost/weak_ptr.hpp>
#include <boost/thread.hpp>

namespace apache { namespace thrift { namespace concurrency {

using boost::shared_ptr;
using boost::weak_ptr;

/**
 * The boost thread class.
 *
 * @version $Id:$
 */
class BoostThread: public Thread {
 public:

  enum STATE {
    uninitialized,
    starting,
    started,
    stopping,
    stopped
  };

  static void* threadMain(void* arg);

 private:
  std::auto_ptr<boost::thread> thread_;
  STATE state_;
  weak_ptr<BoostThread> self_;
  bool detached_;

 public:

  BoostThread(bool detached, shared_ptr<Runnable> runnable) :
    state_(uninitialized),
    detached_(detached) {
      this->Thread::runnable(runnable);
    }

  ~BoostThread() {
    if(!detached_) {
      try {
        join();
      } catch(...) {
        // We're really hosed.
      }
    }
  }

  void start() {
    if (state_ != uninitialized) {
      return;
    }

  // Create reference
    shared_ptr<BoostThread>* selfRef = new shared_ptr<BoostThread>();
    *selfRef = self_.lock();

    state_ = starting;

    thread_ = std::auto_ptr<boost::thread>(new boost::thread(boost::bind(threadMain, (void*)selfRef)));

    if(detached_)
      thread_->detach();
  }

  void join() {
    if (!detached_ && state_ != uninitialized) {
      thread_->join();
    }
  }

  Thread::id_t getId() {
    return thread_.get() ? thread_->get_id() : boost::thread::id();
  }

  shared_ptr<Runnable> runnable() const { return Thread::runnable(); }

  void runnable(shared_ptr<Runnable> value) { Thread::runnable(value); }

  void weakRef(shared_ptr<BoostThread> self) {
    assert(self.get() == this);
    self_ = weak_ptr<BoostThread>(self);
  }
};

void* BoostThread::threadMain(void* arg) {
  shared_ptr<BoostThread> thread = *(shared_ptr<BoostThread>*)arg;
  delete reinterpret_cast<shared_ptr<BoostThread>*>(arg);

  if (thread == NULL) {
    return (void*)0;
  }

  if (thread->state_ != starting) {
    return (void*)0;
  }

  thread->state_ = started;
  thread->runnable()->run();

  if (thread->state_ != stopping && thread->state_ != stopped) {
    thread->state_ = stopping;
  }
  return (void*)0;
}

/**
 * POSIX Thread factory implementation
 */
class BoostThreadFactory::Impl {

 private:
  bool detached_;

 public:

  Impl(bool detached) :
    detached_(detached) {}

  /**
   * Creates a new POSIX thread to run the runnable object
   *
   * @param runnable A runnable object
   */
  shared_ptr<Thread> newThread(shared_ptr<Runnable> runnable) const {
    shared_ptr<BoostThread> result = shared_ptr<BoostThread>(new BoostThread(detached_, runnable));
    result->weakRef(result);
    runnable->thread(result);
    return result;
  }

  bool isDetached() const { return detached_; }

  void setDetached(bool value) { detached_ = value; }

  Thread::id_t getCurrentThreadId() const {
    return boost::this_thread::get_id();
  }
};

BoostThreadFactory::BoostThreadFactory(bool detached) :
  impl_(new BoostThreadFactory::Impl(detached)) {}

shared_ptr<Thread> BoostThreadFactory::newThread(shared_ptr<Runnable> runnable) const { return impl_->newThread(runnable); }

bool BoostThreadFactory::isDetached() const { return impl_->isDetached(); }

void BoostThreadFactory::setDetached(bool value) { impl_->setDetached(value); }

Thread::id_t BoostThreadFactory::getCurrentThreadId() const { return impl_->getCurrentThreadId(); }

}}} // apache::thrift::concurrency
<|endoftext|>


<commit_before>// -*- coding: us-ascii-unix -*-
// Copyright 2012 Lukas Kemmer
//
// Licensed under the Apache License, Version 2.0 (the "License"); you
// may not use this file except in compliance with the License. You
// may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.

#include <tuple>
#include "bitmap/gradient.hh"
#include "util/either.hh"
#include "util/index.hh"

namespace faint{

template<typename T>
bool point_less(const T& lhs, const T& rhs){
  return std::tie(lhs.x, lhs.y) < std::tie(rhs.x, rhs.y);
}

static bool operator<(const Point& lhs, const Point& rhs){
  return point_less(lhs, rhs);
}

static bool operator<(const Radii& lhs, const Radii& rhs){
  return point_less(lhs, rhs);
}

ColorStop::ColorStop()
  : m_color(0,0,0),
    m_offset(0.0)
{}

ColorStop::ColorStop(const Color& c, double offset)
  : m_color(c),
    m_offset(offset)
{}

Color ColorStop::GetColor() const{
  return m_color;
}

double ColorStop::GetOffset() const{
  return m_offset;
}

bool ColorStop::operator<(const ColorStop& other) const{
  return m_offset < other.m_offset ||
    (m_offset == other.m_offset && m_color < other.m_color);
}

bool ColorStop::operator==(const ColorStop& other) const{
  return m_color == other.m_color &&
    m_offset == other.m_offset;
}

bool ColorStop::operator!=(const ColorStop& other) const{
  return m_color != other.m_color ||
    m_offset != other.m_offset;
}

LinearGradient::LinearGradient()
  : m_angle(Angle::Zero()),
    m_objectAligned(true)
{}

LinearGradient::LinearGradient(const Angle& angle, const color_stops_t& stops)
  : m_angle(angle),
    m_objectAligned(true),
    m_stops(stops)
{}

void LinearGradient::Add(const ColorStop& stop){
  m_stops.push_back(stop);
}

void LinearGradient::Remove(const Index& index){
  assert(has_index(m_stops, index));
  m_stops.erase(begin(m_stops) + index.Get());
}

Angle LinearGradient::GetAngle() const{
  return m_angle;
}

Index LinearGradient::GetNumStops() const{
  return Index(resigned(m_stops.size()));
}

bool LinearGradient::GetObjectAligned() const{
  return m_objectAligned;
}

const ColorStop& LinearGradient::GetStop(const Index& index) const{
  assert(has_index(m_stops, index));
  return m_stops[to_size_t(index)];
}

const color_stops_t& LinearGradient::GetStops() const{
  return m_stops;
}

void LinearGradient::SetAngle(const Angle& a){
  m_angle = a;
}

void LinearGradient::SetObjectAligned(bool objectAligned){
  m_objectAligned = objectAligned;
}

void LinearGradient::SetStop(const Index& index, const ColorStop& stop){
  assert(has_index(m_stops, index));
  m_stops[to_size_t(index)] = stop;
}

void LinearGradient::SetStops(const color_stops_t& stops){
  m_stops = stops;
}

inline std::tuple<Angle, bool, const color_stops_t&> tupeled(
  const LinearGradient& g)
{
  return std::make_tuple(g.GetAngle(),
    g.GetObjectAligned(),
    std::cref(g.GetStops()));
}

bool LinearGradient::operator<(const LinearGradient& other) const{
  return tupeled(*this) < tupeled(other);
}

bool LinearGradient::operator==(const LinearGradient& other) const{
  return tupeled(*this) == tupeled(other);
}

bool LinearGradient::operator!=(const LinearGradient& other) const{
  return !(*this == other);
}

bool LinearGradient::operator>(const LinearGradient& other) const{
  return tupeled(*this) > tupeled(other);
}

LinearGradient unrotated(const LinearGradient& g){
  LinearGradient g2(Angle::Zero(), g.GetStops());
  g2.SetObjectAligned(g.GetObjectAligned());
  return g2;
}

LinearGradient with_angle(const LinearGradient& g, const Angle& angle){
  LinearGradient g2(g);
  g2.SetAngle(angle);
  return g2;
}

inline std::tuple<Point, bool, Radii, const color_stops_t&> tupeled(
  const RadialGradient& g)
{
  return std::make_tuple(g.GetCenter(),
    g.GetObjectAligned(),
    g.GetRadii(),
    std::cref(g.GetStops()));
}

RadialGradient::RadialGradient()
  : m_center(0,0),
    m_objectAligned(true),
    m_radii(0,0)
{}

RadialGradient::RadialGradient(const Point& center,
  const Radii& radii,
  const color_stops_t& stops)
  : m_center(center),
    m_objectAligned(true),
    m_radii(radii),
    m_stops(stops)
{}

void RadialGradient::Add(const ColorStop& stop){
  m_stops.push_back(stop);
}

Point RadialGradient::GetCenter() const{
  return m_center;
}

Index RadialGradient::GetNumStops() const{
  return Index(resigned(m_stops.size()));
}

bool RadialGradient::GetObjectAligned() const{
  return m_objectAligned;
}

Radii RadialGradient::GetRadii() const{
  return m_radii;
}

ColorStop RadialGradient::GetStop(const Index& index) const{
  assert(has_index(m_stops, index));
  return m_stops[to_size_t(index)];
}

const color_stops_t& RadialGradient::GetStops() const{
  return m_stops;
}

void RadialGradient::Remove(const Index& index){
  assert(has_index(m_stops, index));
  m_stops.erase(begin(m_stops) + index.Get());
}

void RadialGradient::SetCenter(const Point& center){
  m_center = center;
}

void RadialGradient::SetObjectAligned(bool value){
  m_objectAligned = value;
}

void RadialGradient::SetRadii(const Radii& radii){
  m_radii = radii;
}

void RadialGradient::SetStop(const Index& index, const ColorStop& stop){
  assert(has_index(m_stops, index));
  m_stops[to_size_t(index)] = stop;
}

void RadialGradient::SetStops(const color_stops_t& stops){
  m_stops = stops;
}

bool RadialGradient::operator==(const RadialGradient& other) const{
  return tupeled(*this) == tupeled(other);
}

bool RadialGradient::operator!=(const RadialGradient& other) const{
  return !(*this == other);
}

bool RadialGradient::operator<(const RadialGradient& other) const{
  return tupeled(*this) < tupeled(other);
}

bool RadialGradient::operator>(const RadialGradient& other) const{
  return tupeled(*this) > tupeled(other);
}

class Gradient::GradientImpl{
public:
  explicit GradientImpl(const LinearGradient& linear)
    : gradient(linear)
  {}

  explicit GradientImpl(const RadialGradient& radial)
    : gradient(radial)
  {}

  Either<LinearGradient, RadialGradient> gradient;
};

Gradient::Gradient(const LinearGradient& linear)
  : m_impl(std::make_unique<GradientImpl>(linear))
{}

Gradient::Gradient(const RadialGradient& radial)
  : m_impl(std::make_unique<GradientImpl>(radial))
{}

Gradient::Gradient(const Gradient& other)
  : m_impl(std::make_unique<GradientImpl>(*other.m_impl))
{}

Gradient::~Gradient(){
  // This destructor must be defined or unique_ptr to forward-declared
  // GradientImpl won't compile.
}

color_stops_t Gradient::GetStops() const{
  return m_impl->gradient.Visit(
    [](const LinearGradient& g){
      return g.GetStops();
    },
    [](const RadialGradient& g){
      return g.GetStops();
    });
}

bool Gradient::IsLinear() const{
  return m_impl->gradient.Get<LinearGradient>().IsSet();
}

bool Gradient::IsRadial() const{
  return m_impl->gradient.Get<RadialGradient>().IsSet();
}

bool Gradient::operator==(const Gradient& other) const{
  return m_impl->gradient == other.m_impl->gradient;
}

const LinearGradient& Gradient::GetLinear() const{
  return m_impl->gradient.Expect<LinearGradient>();
}

const RadialGradient& Gradient::GetRadial() const{
  return m_impl->gradient.Expect<RadialGradient>();
}

} // namespace
<commit_msg>More tuple use.<commit_after>// -*- coding: us-ascii-unix -*-
// Copyright 2012 Lukas Kemmer
//
// Licensed under the Apache License, Version 2.0 (the "License"); you
// may not use this file except in compliance with the License. You
// may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.

#include <tuple>
#include "bitmap/gradient.hh"
#include "util/either.hh"
#include "util/index.hh"

namespace faint{

template<typename T>
bool point_less(const T& lhs, const T& rhs){
  return std::tie(lhs.x, lhs.y) < std::tie(rhs.x, rhs.y);
}

static bool operator<(const Point& lhs, const Point& rhs){
  // Required for operator< on tuple containing Point
  return point_less(lhs, rhs);
}

static bool operator<(const Radii& lhs, const Radii& rhs){
  // Required for operator< on tuple containing Point
  return point_less(lhs, rhs);
}

inline std::tuple<Color, double> tupled(const ColorStop& s){
  return std::make_tuple(s.GetColor(), s.GetOffset());
}

ColorStop::ColorStop()
  : m_color(0,0,0),
    m_offset(0.0)
{}

ColorStop::ColorStop(const Color& c, double offset)
  : m_color(c),
    m_offset(offset)
{}

Color ColorStop::GetColor() const{
  return m_color;
}

double ColorStop::GetOffset() const{
  return m_offset;
}

bool ColorStop::operator<(const ColorStop& other) const{
  return std::tie(m_offset, m_color) < std::tie(other.m_offset, other.m_color);
}

bool ColorStop::operator==(const ColorStop& other) const{
  return tupled(*this) == tupled(other);
}

bool ColorStop::operator!=(const ColorStop& other) const{
  return !(*this == other);
}

LinearGradient::LinearGradient()
  : m_angle(Angle::Zero()),
    m_objectAligned(true)
{}

LinearGradient::LinearGradient(const Angle& angle, const color_stops_t& stops)
  : m_angle(angle),
    m_objectAligned(true),
    m_stops(stops)
{}

void LinearGradient::Add(const ColorStop& stop){
  m_stops.push_back(stop);
}

void LinearGradient::Remove(const Index& index){
  assert(has_index(m_stops, index));
  m_stops.erase(begin(m_stops) + index.Get());
}

Angle LinearGradient::GetAngle() const{
  return m_angle;
}

Index LinearGradient::GetNumStops() const{
  return Index(resigned(m_stops.size()));
}

bool LinearGradient::GetObjectAligned() const{
  return m_objectAligned;
}

const ColorStop& LinearGradient::GetStop(const Index& index) const{
  assert(has_index(m_stops, index));
  return m_stops[to_size_t(index)];
}

const color_stops_t& LinearGradient::GetStops() const{
  return m_stops;
}

void LinearGradient::SetAngle(const Angle& a){
  m_angle = a;
}

void LinearGradient::SetObjectAligned(bool objectAligned){
  m_objectAligned = objectAligned;
}

void LinearGradient::SetStop(const Index& index, const ColorStop& stop){
  assert(has_index(m_stops, index));
  m_stops[to_size_t(index)] = stop;
}

void LinearGradient::SetStops(const color_stops_t& stops){
  m_stops = stops;
}

inline std::tuple<Angle, bool, const color_stops_t&> tupled(
  const LinearGradient& g)
{
  return std::make_tuple(g.GetAngle(),
    g.GetObjectAligned(),
    std::cref(g.GetStops()));
}

bool LinearGradient::operator<(const LinearGradient& other) const{
  return tupled(*this) < tupled(other);
}

bool LinearGradient::operator==(const LinearGradient& other) const{
  return tupled(*this) == tupled(other);
}

bool LinearGradient::operator!=(const LinearGradient& other) const{
  return !(*this == other);
}

bool LinearGradient::operator>(const LinearGradient& other) const{
  return tupled(*this) > tupled(other);
}

LinearGradient unrotated(const LinearGradient& g){
  LinearGradient g2(Angle::Zero(), g.GetStops());
  g2.SetObjectAligned(g.GetObjectAligned());
  return g2;
}

LinearGradient with_angle(const LinearGradient& g, const Angle& angle){
  LinearGradient g2(g);
  g2.SetAngle(angle);
  return g2;
}

inline std::tuple<Point, bool, Radii, const color_stops_t&> tupled(
  const RadialGradient& g)
{
  return std::make_tuple(g.GetCenter(),
    g.GetObjectAligned(),
    g.GetRadii(),
    std::cref(g.GetStops()));
}

RadialGradient::RadialGradient()
  : m_center(0,0),
    m_objectAligned(true),
    m_radii(0,0)
{}

RadialGradient::RadialGradient(const Point& center,
  const Radii& radii,
  const color_stops_t& stops)
  : m_center(center),
    m_objectAligned(true),
    m_radii(radii),
    m_stops(stops)
{}

void RadialGradient::Add(const ColorStop& stop){
  m_stops.push_back(stop);
}

Point RadialGradient::GetCenter() const{
  return m_center;
}

Index RadialGradient::GetNumStops() const{
  return Index(resigned(m_stops.size()));
}

bool RadialGradient::GetObjectAligned() const{
  return m_objectAligned;
}

Radii RadialGradient::GetRadii() const{
  return m_radii;
}

ColorStop RadialGradient::GetStop(const Index& index) const{
  assert(has_index(m_stops, index));
  return m_stops[to_size_t(index)];
}

const color_stops_t& RadialGradient::GetStops() const{
  return m_stops;
}

void RadialGradient::Remove(const Index& index){
  assert(has_index(m_stops, index));
  m_stops.erase(begin(m_stops) + index.Get());
}

void RadialGradient::SetCenter(const Point& center){
  m_center = center;
}

void RadialGradient::SetObjectAligned(bool value){
  m_objectAligned = value;
}

void RadialGradient::SetRadii(const Radii& radii){
  m_radii = radii;
}

void RadialGradient::SetStop(const Index& index, const ColorStop& stop){
  assert(has_index(m_stops, index));
  m_stops[to_size_t(index)] = stop;
}

void RadialGradient::SetStops(const color_stops_t& stops){
  m_stops = stops;
}

bool RadialGradient::operator==(const RadialGradient& other) const{
  return tupled(*this) == tupled(other);
}

bool RadialGradient::operator!=(const RadialGradient& other) const{
  return !(*this == other);
}

bool RadialGradient::operator<(const RadialGradient& other) const{
  return tupled(*this) < tupled(other);
}

bool RadialGradient::operator>(const RadialGradient& other) const{
  return tupled(*this) > tupled(other);
}

class Gradient::GradientImpl{
public:
  explicit GradientImpl(const LinearGradient& linear)
    : gradient(linear)
  {}

  explicit GradientImpl(const RadialGradient& radial)
    : gradient(radial)
  {}

  Either<LinearGradient, RadialGradient> gradient;
};

Gradient::Gradient(const LinearGradient& linear)
  : m_impl(std::make_unique<GradientImpl>(linear))
{}

Gradient::Gradient(const RadialGradient& radial)
  : m_impl(std::make_unique<GradientImpl>(radial))
{}

Gradient::Gradient(const Gradient& other)
  : m_impl(std::make_unique<GradientImpl>(*other.m_impl))
{}

Gradient::~Gradient(){
  // This destructor must be defined or unique_ptr to forward-declared
  // GradientImpl won't compile.
}

color_stops_t Gradient::GetStops() const{
  return m_impl->gradient.Visit(
    [](const LinearGradient& g){
      return g.GetStops();
    },
    [](const RadialGradient& g){
      return g.GetStops();
    });
}

bool Gradient::IsLinear() const{
  return m_impl->gradient.Get<LinearGradient>().IsSet();
}

bool Gradient::IsRadial() const{
  return m_impl->gradient.Get<RadialGradient>().IsSet();
}

bool Gradient::operator==(const Gradient& other) const{
  return m_impl->gradient == other.m_impl->gradient;
}

const LinearGradient& Gradient::GetLinear() const{
  return m_impl->gradient.Expect<LinearGradient>();
}

const RadialGradient& Gradient::GetRadial() const{
  return m_impl->gradient.Expect<RadialGradient>();
}

} // namespace
<|endoftext|>


<commit_before><commit_msg>fix main<commit_after><|endoftext|>


<commit_before>/*
    This file is part of KMail, the KDE mail client.
    Copyright (c) 2000 Don Sanders <sanders@kde.org>

    KMail is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License, version 2, as
    published by the Free Software Foundation.

    KMail 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 GNU
    General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "kmstartup.h"
#include <kdepim-compat.h> // for KDE_signal, remove in KDEPIM 4.2

#include "kmkernel.h" //control center
#include "kcursorsaver.h"

#include <klocale.h>
#include <kcomponentdata.h>
#include <kconfig.h>
#include <kstandarddirs.h>
#include <kmessagebox.h>
#include <kcrash.h>
#include <kglobal.h>
#include <kaboutdata.h>
#include <kiconloader.h>
#include <kconfiggroup.h>
#include <kde_file.h>

#include <QHostInfo>

#include <errno.h>
#include <sys/types.h>
#include <sys/param.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <qfile.h>

#undef Status // stupid X headers

extern "C" {

// Crash recovery signal handler
void kmsignalHandler(int sigId)
{
  kmsetSignalHandler(SIG_DFL);
  fprintf(stderr, "*** KMail got signal %d (Exiting)\n", sigId);
  // try to cleanup all windows
  if (kmkernel) kmkernel->dumpDeadLetters();
  ::exit(-1); //
}

// Crash recovery signal handler
void kmcrashHandler(int sigId)
{
  kmsetSignalHandler(SIG_DFL);
  fprintf(stderr, "*** KMail got signal %d (Crashing)\n", sigId);
  // try to cleanup all windows
  if (kmkernel) kmkernel->dumpDeadLetters();
  // Return to DrKonqi.
}
//-----------------------------------------------------------------------------

void kmsetSignalHandler(void (*handler)(int))
{
  KDE_signal(SIGKILL, handler);
  KDE_signal(SIGTERM, handler);
  KDE_signal(SIGHUP,  handler);
  KCrash::setEmergencySaveFunction(kmcrashHandler);
}

}
//-----------------------------------------------------------------------------

namespace KMail {

void checkConfigUpdates() {
  static const char * const updates[] = {
    "9",
    "3.1-update-identities",
    "3.1-use-identity-uoids",
    "3.1-new-mail-notification",
    "3.2-update-loop-on-goto-unread-settings",
    "3.1.4-dont-use-UOID-0-for-any-identity",  //krazy:exclude=spelling
    "3.2-misc",
    "3.2-moves",
    "3.3-use-ID-for-accounts",
    "3.3-update-filter-rules",
    "3.3-move-identities-to-own-file",
    "3.3-aegypten-kpgprc-to-kmailrc",
    "3.3-aegypten-kpgprc-to-libkleopatrarc",
    "3.3-aegypten-emailidentities-split-sign-encr-keys",
    "3.3-misc",
    "3.3b1-misc",
    "3.4-misc",
    "3.4a",
    "3.4b",
    "3.4.1",
    "3.5.4",
    "3.5.7-imap-flag-migration",
    "4.0-misc",
    "4.2"
  };
  static const int numUpdates = sizeof updates / sizeof *updates;
  // Warning: do not remove entries in the above array, or the update-level check below will break

  KConfig * config = KMKernel::config();
  KConfigGroup startup( config, "Startup" );
  const int configUpdateLevel = startup.readEntry( "update-level", 0 );
  if ( configUpdateLevel == numUpdates ) // Optimize for the common case that everything is OK
    return;

  for ( int i = configUpdateLevel ; i < numUpdates ; ++i ) {
    config->checkUpdate( updates[i], "kmail.upd" );
  }
  startup.writeEntry( "update-level", numUpdates );
}

void lockOrDie() {
// Check and create a lock file to prevent concurrent access to kmail files
  QString appName = KGlobal::mainComponent().componentName();
  if ( appName.isEmpty() )
    appName = "kmail";

  QString programName;
  const KAboutData *about = KGlobal::mainComponent().aboutData();
  if ( about )
    programName = about->programName();
  if ( programName.isEmpty() )
    programName = i18n("KMail");

  QString lockLocation = KStandardDirs::locateLocal("data", "kmail/lock");
  KConfig config(lockLocation, KConfig::SimpleConfig);
  KConfigGroup group(&config, "");
  int oldPid = group.readEntry("pid", -1 );
  kDebug() << "oldPid=" << oldPid;
  const QString oldHostName = group.readEntry("hostname");
  const QString oldAppName = group.readEntry( "appName", appName );
  const QString oldProgramName = group.readEntry( "programName", programName );
  const QString hostName = QHostInfo::localHostName();
  bool first_instance = false;
  if ( oldPid == -1 ) {
    first_instance = true;
  } else if ( hostName == oldHostName && oldPid != getpid() ) {
    // check if the lock file is stale
#ifdef Q_OS_LINUX //krazy:exclude=cpp
    if ( ::access("/proc", X_OK ) == 0 ) {
      // On linux with /proc we can even check that
      // it's really kmail and not something else
      char path_buffer[MAXPATHLEN + 1];
      path_buffer[MAXPATHLEN] = 0;
      const QString procPath = QString( "/proc/%1/exe" ).arg( oldPid );
      const int length =
        readlink( procPath.toLatin1(), path_buffer, MAXPATHLEN );
      if ( length == -1 ) { // no such pid
        first_instance = true;
      } else {
        path_buffer[length] = '\0';
        const QString path = QFile::decodeName( path_buffer );
        kDebug() << path;
        const int pos = path.lastIndexOf( '/' );
        const QString fileName = path.mid( pos + 1 );
        kDebug() << "Found process" << oldPid
                     << "running. It's:" << fileName;
        first_instance = fileName != "kmail" && fileName != "kontact";
      }
    } else
#endif
    {
      // Otherwise we just check if the other pid is currently running.
      // Not 100% correct but better safe than sorry.
      if ( kill(oldPid, 0) == -1 )
        first_instance = ( errno == ESRCH );
    }
  }

  if ( !first_instance ) {
    QString msg;
    if ( oldHostName == hostName ) {
      // this can only happen if the user is running this application on
      // different displays on the same machine. All other cases will be
      // taken care of by KUniqueApplication()
      if ( oldAppName == appName )
        msg = i18n("%1 already seems to be running on another display on "
                   "this machine. Running %2 more than once "
                   "can cause the loss of mail. You should not start %1 "
                   "unless you are sure that it is not already running.",
                   programName, programName );
              // QString::arg( st ) only replaces the first occurrence of %1
              // with st while QString::arg( s1, s2 ) replacess all occurrences
              // of %1 with s1 and all occurrences of %2 with s2. So don't
              // even think about changing the above to .arg( programName ).
      else
        msg = i18n("%1 seems to be running on another display on this "
                   "machine. Running %1 and %2 at the same "
                   "time can cause the loss of mail. You should not start %2 "
                   "unless you are sure that %1 is not running.",
                   oldProgramName, programName );
    }
    else {
      if ( oldAppName == appName )
        msg = i18n("%1 already seems to be running on %2. Running %1 more "
                   "than once can cause the loss of mail. You should not "
                   "start %1 on this computer unless you are sure that it is "
                   "not already running on %2.",
                   programName, oldHostName );
      else
        msg = i18n("%1 seems to be running on %3. Running %1 and %2 at the "
                   "same time can cause the loss of mail. You should not "
                   "start %2 on this computer unless you are sure that %1 is "
                   "not running on %3.",
                    oldProgramName, programName, oldHostName );
    }

    KCursorSaver idle( KBusyPtr::idle() );
    if ( KMessageBox::No ==
         KMessageBox::warningYesNo( 0, msg, QString(),
           KGuiItem(i18nc("Start kmail even when another instance is running.", "Start %1", programName )),
           KGuiItem(i18nc("Do not start another kmail instance.","Exit")) ) ) {
      exit(1);
    }
  }

  qlonglong pid = static_cast<qlonglong>( getpid() );
  group.writeEntry( "pid", pid );
  group.writeEntry( "hostname", hostName );
  group.writeEntry( "appName", appName );
  group.writeEntry( "programName", programName );
  group.sync();
}

void insertLibraryCataloguesAndIcons() {
  static const char * const catalogs[] = {
    "libkdepim",
    "libksieve",
    "libkleopatra",
    "libkmime"
  };

  KLocale * l = KGlobal::locale();
  KIconLoader * il = KIconLoader::global();
  for ( unsigned int i = 0 ; i < sizeof catalogs / sizeof *catalogs ; ++i ) {
    l->insertCatalog( catalogs[i] );
    il->addAppDir( catalogs[i] );
  }

}

void cleanup()
{
  const QString lockLocation = KStandardDirs::locateLocal("data", "kmail/lock");
  KConfig config(lockLocation, KConfig::SimpleConfig);
  KConfigGroup group(&config, "");
  group.writeEntry("pid", -1);
  group.sync();
}
}
<commit_msg>The removed line said: for KDE_signal, remove in KDEPIM 4.2 It will be removed for KDEPIM 4.4 instead. Also remove the handle for SIGKILL, that is impossible to handle.<commit_after>/*
    This file is part of KMail, the KDE mail client.
    Copyright (c) 2000 Don Sanders <sanders@kde.org>

    KMail is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License, version 2, as
    published by the Free Software Foundation.

    KMail 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 GNU
    General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "kmstartup.h"

#include "kmkernel.h" //control center
#include "kcursorsaver.h"

#include <klocale.h>
#include <kcomponentdata.h>
#include <kconfig.h>
#include <kstandarddirs.h>
#include <kmessagebox.h>
#include <kcrash.h>
#include <kglobal.h>
#include <kaboutdata.h>
#include <kiconloader.h>
#include <kconfiggroup.h>
#include <kde_file.h>

#include <QHostInfo>

#include <errno.h>
#include <sys/types.h>
#include <sys/param.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <qfile.h>

#undef Status // stupid X headers

extern "C" {

// Crash recovery signal handler
void kmsignalHandler(int sigId)
{
  kmsetSignalHandler(SIG_DFL);
  fprintf(stderr, "*** KMail got signal %d (Exiting)\n", sigId);
  // try to cleanup all windows
  if (kmkernel) kmkernel->dumpDeadLetters();
  ::exit(-1); //
}

// Crash recovery signal handler
void kmcrashHandler(int sigId)
{
  kmsetSignalHandler(SIG_DFL);
  fprintf(stderr, "*** KMail got signal %d (Crashing)\n", sigId);
  // try to cleanup all windows
  if (kmkernel) kmkernel->dumpDeadLetters();
  // Return to DrKonqi.
}
//-----------------------------------------------------------------------------

void kmsetSignalHandler(void (*handler)(int))
{
  KDE_signal(SIGTERM, handler);
  KDE_signal(SIGHUP,  handler);
  KCrash::setEmergencySaveFunction(kmcrashHandler);
}

}
//-----------------------------------------------------------------------------

namespace KMail {

void checkConfigUpdates() {
  static const char * const updates[] = {
    "9",
    "3.1-update-identities",
    "3.1-use-identity-uoids",
    "3.1-new-mail-notification",
    "3.2-update-loop-on-goto-unread-settings",
    "3.1.4-dont-use-UOID-0-for-any-identity",  //krazy:exclude=spelling
    "3.2-misc",
    "3.2-moves",
    "3.3-use-ID-for-accounts",
    "3.3-update-filter-rules",
    "3.3-move-identities-to-own-file",
    "3.3-aegypten-kpgprc-to-kmailrc",
    "3.3-aegypten-kpgprc-to-libkleopatrarc",
    "3.3-aegypten-emailidentities-split-sign-encr-keys",
    "3.3-misc",
    "3.3b1-misc",
    "3.4-misc",
    "3.4a",
    "3.4b",
    "3.4.1",
    "3.5.4",
    "3.5.7-imap-flag-migration",
    "4.0-misc",
    "4.2"
  };
  static const int numUpdates = sizeof updates / sizeof *updates;
  // Warning: do not remove entries in the above array, or the update-level check below will break

  KConfig * config = KMKernel::config();
  KConfigGroup startup( config, "Startup" );
  const int configUpdateLevel = startup.readEntry( "update-level", 0 );
  if ( configUpdateLevel == numUpdates ) // Optimize for the common case that everything is OK
    return;

  for ( int i = configUpdateLevel ; i < numUpdates ; ++i ) {
    config->checkUpdate( updates[i], "kmail.upd" );
  }
  startup.writeEntry( "update-level", numUpdates );
}

void lockOrDie() {
// Check and create a lock file to prevent concurrent access to kmail files
  QString appName = KGlobal::mainComponent().componentName();
  if ( appName.isEmpty() )
    appName = "kmail";

  QString programName;
  const KAboutData *about = KGlobal::mainComponent().aboutData();
  if ( about )
    programName = about->programName();
  if ( programName.isEmpty() )
    programName = i18n("KMail");

  QString lockLocation = KStandardDirs::locateLocal("data", "kmail/lock");
  KConfig config(lockLocation, KConfig::SimpleConfig);
  KConfigGroup group(&config, "");
  int oldPid = group.readEntry("pid", -1 );
  kDebug() << "oldPid=" << oldPid;
  const QString oldHostName = group.readEntry("hostname");
  const QString oldAppName = group.readEntry( "appName", appName );
  const QString oldProgramName = group.readEntry( "programName", programName );
  const QString hostName = QHostInfo::localHostName();
  bool first_instance = false;
  if ( oldPid == -1 ) {
    first_instance = true;
  } else if ( hostName == oldHostName && oldPid != getpid() ) {
    // check if the lock file is stale
#ifdef Q_OS_LINUX //krazy:exclude=cpp
    if ( ::access("/proc", X_OK ) == 0 ) {
      // On linux with /proc we can even check that
      // it's really kmail and not something else
      char path_buffer[MAXPATHLEN + 1];
      path_buffer[MAXPATHLEN] = 0;
      const QString procPath = QString( "/proc/%1/exe" ).arg( oldPid );
      const int length =
        readlink( procPath.toLatin1(), path_buffer, MAXPATHLEN );
      if ( length == -1 ) { // no such pid
        first_instance = true;
      } else {
        path_buffer[length] = '\0';
        const QString path = QFile::decodeName( path_buffer );
        kDebug() << path;
        const int pos = path.lastIndexOf( '/' );
        const QString fileName = path.mid( pos + 1 );
        kDebug() << "Found process" << oldPid
                     << "running. It's:" << fileName;
        first_instance = fileName != "kmail" && fileName != "kontact";
      }
    } else
#endif
    {
      // Otherwise we just check if the other pid is currently running.
      // Not 100% correct but better safe than sorry.
      if ( kill(oldPid, 0) == -1 )
        first_instance = ( errno == ESRCH );
    }
  }

  if ( !first_instance ) {
    QString msg;
    if ( oldHostName == hostName ) {
      // this can only happen if the user is running this application on
      // different displays on the same machine. All other cases will be
      // taken care of by KUniqueApplication()
      if ( oldAppName == appName )
        msg = i18n("%1 already seems to be running on another display on "
                   "this machine. Running %2 more than once "
                   "can cause the loss of mail. You should not start %1 "
                   "unless you are sure that it is not already running.",
                   programName, programName );
              // QString::arg( st ) only replaces the first occurrence of %1
              // with st while QString::arg( s1, s2 ) replacess all occurrences
              // of %1 with s1 and all occurrences of %2 with s2. So don't
              // even think about changing the above to .arg( programName ).
      else
        msg = i18n("%1 seems to be running on another display on this "
                   "machine. Running %1 and %2 at the same "
                   "time can cause the loss of mail. You should not start %2 "
                   "unless you are sure that %1 is not running.",
                   oldProgramName, programName );
    }
    else {
      if ( oldAppName == appName )
        msg = i18n("%1 already seems to be running on %2. Running %1 more "
                   "than once can cause the loss of mail. You should not "
                   "start %1 on this computer unless you are sure that it is "
                   "not already running on %2.",
                   programName, oldHostName );
      else
        msg = i18n("%1 seems to be running on %3. Running %1 and %2 at the "
                   "same time can cause the loss of mail. You should not "
                   "start %2 on this computer unless you are sure that %1 is "
                   "not running on %3.",
                    oldProgramName, programName, oldHostName );
    }

    KCursorSaver idle( KBusyPtr::idle() );
    if ( KMessageBox::No ==
         KMessageBox::warningYesNo( 0, msg, QString(),
           KGuiItem(i18nc("Start kmail even when another instance is running.", "Start %1", programName )),
           KGuiItem(i18nc("Do not start another kmail instance.","Exit")) ) ) {
      exit(1);
    }
  }

  qlonglong pid = static_cast<qlonglong>( getpid() );
  group.writeEntry( "pid", pid );
  group.writeEntry( "hostname", hostName );
  group.writeEntry( "appName", appName );
  group.writeEntry( "programName", programName );
  group.sync();
}

void insertLibraryCataloguesAndIcons() {
  static const char * const catalogs[] = {
    "libkdepim",
    "libksieve",
    "libkleopatra",
    "libkmime"
  };

  KLocale * l = KGlobal::locale();
  KIconLoader * il = KIconLoader::global();
  for ( unsigned int i = 0 ; i < sizeof catalogs / sizeof *catalogs ; ++i ) {
    l->insertCatalog( catalogs[i] );
    il->addAppDir( catalogs[i] );
  }

}

void cleanup()
{
  const QString lockLocation = KStandardDirs::locateLocal("data", "kmail/lock");
  KConfig config(lockLocation, KConfig::SimpleConfig);
  KConfigGroup group(&config, "");
  group.writeEntry("pid", -1);
  group.sync();
}
}
<|endoftext|>


<commit_before>/*
    knscoring.cpp

    KNode, the KDE newsreader
    Copyright (c) 1999-2001 the KNode authors.
    See file AUTHORS for details

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software Foundation,
    Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, US
*/

#include <qstring.h>

#if QT_VERSION < 300
#  define Q_ASSERT ASSERT
#endif

#include <kwin.h>
#include <kscoringeditor.h>

#include "knscoring.h"
#include "knaccountmanager.h"
#include "kngroupmanager.h"
#include "utilities.h"
#include "knglobals.h"

//----------------------------------------------------------------------------
NotifyCollection* KNScorableArticle::notifyC = 0;

KNScorableArticle::KNScorableArticle(KNRemoteArticle* a)
  : ScorableArticle(), _a(a)
{
}

KNScorableArticle::~KNScorableArticle()
{
}

void KNScorableArticle::addScore(short s)
{
  _a->setScore(_a->score()+s);
  _a->setChanged(true);
}

void KNScorableArticle::changeColor(const QColor& c)
{
  _a->setColor(c);
}

void KNScorableArticle::displayMessage(const QString& s)
{
  if (!_a->isNew()) return;
  if (!notifyC) notifyC = new NotifyCollection();
  notifyC->addNote(*this,s);
}

QString KNScorableArticle::from() const
{
  return _a->from()->asUnicodeString();
}

QString KNScorableArticle::subject() const
{
  return _a->subject()->asUnicodeString();
}

QString KNScorableArticle::getHeaderByType(const QString& s) const
{
  KMime::Headers::Base *h = _a->getHeaderByType(s.latin1());
  if (!h) return "";
  QString t = _a->getHeaderByType(s.latin1())->asUnicodeString();
  Q_ASSERT( t );
  return t;
}

//----------------------------------------------------------------------------

KNScorableGroup::KNScorableGroup()
{
}

KNScorableGroup::~KNScorableGroup()
{
}

//----------------------------------------------------------------------------

KNScoringManager::KNScoringManager()
{
}

KNScoringManager::~KNScoringManager()
{
}

QStringList KNScoringManager::getGroups() const
{
  KNAccountManager *am = knGlobals.accManager;
  KNNntpAccount *ac = am->first();
  QStringList res;
  while (ac) {
    QStringList groups;
    knGlobals.grpManager->getSubscribed(ac,groups);
    res += groups;
    ac = am->next();
  }
  res.sort();
  return res;
}

QStringList KNScoringManager::getDefaultHeaders() const
{
  QStringList l = KScoringManager::getDefaultHeaders();
  l << "Lines";
  l << "References";
  return l;
}

void KNScoringManager::configure()
{
  KScoringEditor *dlg = KScoringEditor::createEditor(this, knGlobals.topWidget);

  if (dlg) {
    dlg->show();
    KWin::setActiveWindow(dlg->winId());
  }
}

#include "knscoring.moc"
<commit_msg>Q_ASSERT wants a bool, not a QString. Did this actually compile before??<commit_after>/*
    knscoring.cpp

    KNode, the KDE newsreader
    Copyright (c) 1999-2001 the KNode authors.
    See file AUTHORS for details

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software Foundation,
    Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, US
*/

#include <qstring.h>

#if QT_VERSION < 300
#  define Q_ASSERT ASSERT
#endif

#include <kwin.h>
#include <kscoringeditor.h>

#include "knscoring.h"
#include "knaccountmanager.h"
#include "kngroupmanager.h"
#include "utilities.h"
#include "knglobals.h"

//----------------------------------------------------------------------------
NotifyCollection* KNScorableArticle::notifyC = 0;

KNScorableArticle::KNScorableArticle(KNRemoteArticle* a)
  : ScorableArticle(), _a(a)
{
}

KNScorableArticle::~KNScorableArticle()
{
}

void KNScorableArticle::addScore(short s)
{
  _a->setScore(_a->score()+s);
  _a->setChanged(true);
}

void KNScorableArticle::changeColor(const QColor& c)
{
  _a->setColor(c);
}

void KNScorableArticle::displayMessage(const QString& s)
{
  if (!_a->isNew()) return;
  if (!notifyC) notifyC = new NotifyCollection();
  notifyC->addNote(*this,s);
}

QString KNScorableArticle::from() const
{
  return _a->from()->asUnicodeString();
}

QString KNScorableArticle::subject() const
{
  return _a->subject()->asUnicodeString();
}

QString KNScorableArticle::getHeaderByType(const QString& s) const
{
  KMime::Headers::Base *h = _a->getHeaderByType(s.latin1());
  if (!h) return "";
  QString t = _a->getHeaderByType(s.latin1())->asUnicodeString();
  Q_ASSERT( !t.isEmpty() );
  return t;
}

//----------------------------------------------------------------------------

KNScorableGroup::KNScorableGroup()
{
}

KNScorableGroup::~KNScorableGroup()
{
}

//----------------------------------------------------------------------------

KNScoringManager::KNScoringManager()
{
}

KNScoringManager::~KNScoringManager()
{
}

QStringList KNScoringManager::getGroups() const
{
  KNAccountManager *am = knGlobals.accManager;
  KNNntpAccount *ac = am->first();
  QStringList res;
  while (ac) {
    QStringList groups;
    knGlobals.grpManager->getSubscribed(ac,groups);
    res += groups;
    ac = am->next();
  }
  res.sort();
  return res;
}

QStringList KNScoringManager::getDefaultHeaders() const
{
  QStringList l = KScoringManager::getDefaultHeaders();
  l << "Lines";
  l << "References";
  return l;
}

void KNScoringManager::configure()
{
  KScoringEditor *dlg = KScoringEditor::createEditor(this, knGlobals.topWidget);

  if (dlg) {
    dlg->show();
    KWin::setActiveWindow(dlg->winId());
  }
}

#include "knscoring.moc"
<|endoftext|>


<commit_before>/*
 * This file is part of the FreeStreamer project,
 * (C)Copyright 2011 Matias Muhonen <mmu@iki.fi>
 * See the file ''LICENSE'' for using the code.
 */

#include "audio_stream.h"

#include <pthread.h>

//#define AS_DEBUG 1

#if !defined (AS_DEBUG)
#define AS_TRACE(...) do {} while (0)
#else
#define AS_TRACE(...) printf(__VA_ARGS__)
#endif

namespace astreamer {

/* Create HTTP stream as Audio_Stream (this) as the delegate */
Audio_Stream::Audio_Stream(CFURLRef url) :
    m_delegate(0),
    m_httpStreamRunning(false),
    m_audioStreamParserRunning(false),
    m_state(STOPPED),
    m_httpStream(new HTTP_Stream(url, this)),
    m_audioQueue(new Audio_Queue())
{
    m_audioQueue->m_delegate = this;
}

Audio_Stream::~Audio_Stream()
{
    close();

    m_httpStream->m_delegate = 0;
    delete m_httpStream, m_httpStream = 0;

    m_audioQueue->m_delegate = 0;
    delete m_audioQueue, m_audioQueue = 0;
}

void Audio_Stream::open()
{
    if (m_httpStreamRunning) {
        AS_TRACE("%s: already running: return\n", __PRETTY_FUNCTION__);
        /* Already running */
        return;
    }

    if (m_httpStream->open()) {
        AS_TRACE("%s: HTTP stream opened, buffering...\n", __PRETTY_FUNCTION__);
        m_httpStreamRunning = true;
        setState(BUFFERING);
    } else {
        AS_TRACE("%s: failed to open the HTTP stream\n", __PRETTY_FUNCTION__);
        setState(FAILED);
    }
}

void Audio_Stream::close()
{
    /* Close the HTTP stream first so that the audio stream parser
       isn't fed with more data to parse */
    if (m_httpStreamRunning) {
        m_httpStream->close();
        m_httpStreamRunning = false;
    }

    if (m_audioStreamParserRunning) {
        if (AudioFileStreamClose(m_audioFileStream) != 0) {
            AS_TRACE("%s: AudioFileStreamClose failed\n", __PRETTY_FUNCTION__);
        }
        m_audioStreamParserRunning = false;
    }

    m_audioQueue->stop();
}

void Audio_Stream::pause()
{
    m_audioQueue->pause();
}

AudioFileTypeID Audio_Stream::audioStreamTypeFromContentType(std::string contentType)
{
    AudioFileTypeID fileTypeHint = kAudioFileAAC_ADTSType;

    if (contentType.compare("") == 0) {
        AS_TRACE("***** Unable to detect the audio stream type: missing content-type! *****\n");
        goto out;
    }

    if (contentType.compare("audio/mpeg") == 0) {
        fileTypeHint = kAudioFileMP3Type;
        AS_TRACE("kAudioFileMP3Type detected\n");
    } else if (contentType.compare("audio/x-wav") == 0) {
        fileTypeHint = kAudioFileWAVEType;
        AS_TRACE("kAudioFileWAVEType detected\n");
    } else if (contentType.compare("audio/x-aifc") == 0) {
        fileTypeHint = kAudioFileAIFCType;
        AS_TRACE("kAudioFileAIFCType detected\n");
    } else if (contentType.compare("audio/x-aiff") == 0) {
        fileTypeHint = kAudioFileAIFFType;
        AS_TRACE("kAudioFileAIFFType detected\n");
    } else if (contentType.compare("audio/x-m4a") == 0) {
        fileTypeHint = kAudioFileM4AType;
        AS_TRACE("kAudioFileM4AType detected\n");
    } else if (contentType.compare("audio/mp4") == 0) {
        fileTypeHint = kAudioFileMPEG4Type;
        AS_TRACE("kAudioFileMPEG4Type detected\n");
    } else if (contentType.compare("audio/x-caf") == 0) {
        fileTypeHint = kAudioFileCAFType;
        AS_TRACE("kAudioFileCAFType detected\n");
    } else if (contentType.compare("audio/aac") == 0 ||
               contentType.compare("audio/aacp") == 0) {
        fileTypeHint = kAudioFileAAC_ADTSType;
        AS_TRACE("kAudioFileAAC_ADTSType detected\n");
    } else {
        AS_TRACE("***** Unable to detect the audio stream type from content-type %s *****\n", contentType.c_str());
    }

out:
    return fileTypeHint;
}

void Audio_Stream::audioQueueStateChanged(Audio_Queue::State state)
{
    if (state == Audio_Queue::RUNNING) {
        setState(PLAYING);
    } else {
        setState(STOPPED);
    }
}

void Audio_Stream::streamIsReadyRead()
{
    if (m_audioStreamParserRunning) {
        AS_TRACE("%s: parser already running!\n", __PRETTY_FUNCTION__);
        return;
    }

    /* Check if the stream's MIME type begins with audio/ */
    std::string contentType = m_httpStream->contentType();

    const char *audioContentType = "audio/";
    size_t audioContentTypeLength = strlen(audioContentType);

    if (contentType.compare(0, audioContentTypeLength, audioContentType) != 0) {
        closeAndSignalError(AS_ERR_OPEN);
        return;
    }

    /* OK, it should be an audio stream, let's try to open it */
    OSStatus result = AudioFileStreamOpen(this,
                                          propertyValueCallback,
                                          streamDataCallback,
                                          audioStreamTypeFromContentType(contentType),
                                          &m_audioFileStream);

    if (result == 0) {
        AS_TRACE("%s: audio file stream opened.\n", __PRETTY_FUNCTION__);
        m_audioStreamParserRunning = true;
    } else {
        closeAndSignalError(AS_ERR_OPEN);
    }
}

void Audio_Stream::streamHasBytesAvailable(UInt8 *data, CFIndex numBytes)
{
    AS_TRACE("%s: %lu bytes\n", __FUNCTION__, numBytes);

    if (!m_httpStreamRunning) {
        AS_TRACE("%s: stray callback detected!\n", __PRETTY_FUNCTION__);
        return;
    }

    if (m_audioStreamParserRunning) {
        OSStatus result = AudioFileStreamParseBytes(m_audioFileStream, numBytes, data, 0);
        if (result != 0) {
            AS_TRACE("%s: AudioFileStreamParseBytes error %d\n", __PRETTY_FUNCTION__, (int)result);
            closeAndSignalError(AS_ERR_STREAM_PARSE);
        }
    }
}

void Audio_Stream::streamEndEncountered()
{
    AS_TRACE("%s\n", __PRETTY_FUNCTION__);

    if (!m_httpStreamRunning) {
        AS_TRACE("%s: stray callback detected!\n", __PRETTY_FUNCTION__);
        return;
    }

    setState(END_OF_FILE);
    close();
}

void Audio_Stream::streamErrorOccurred()
{
    AS_TRACE("%s\n", __PRETTY_FUNCTION__);

    if (!m_httpStreamRunning) {
        AS_TRACE("%s: stray callback detected!\n", __PRETTY_FUNCTION__);
        return;
    }

    closeAndSignalError(AS_ERR_NETWORK);
}

void Audio_Stream::streamMetaDataAvailable(std::string metaData)
{
    if (m_delegate) {
        m_delegate->audioStreamMetaDataAvailable(metaData);
    }
}

/* private */

void Audio_Stream::closeAndSignalError(int errorCode)
{
    AS_TRACE("%s: error %i\n", __PRETTY_FUNCTION__, errorCode);

    setState(FAILED);
    close();

    if (m_delegate) {
        m_delegate->audioStreamErrorOccurred(errorCode);
    }
}

void Audio_Stream::setState(State state)
{
    if (m_state == state) {
        return;
    }

    m_state = state;

    if (m_delegate) {
        m_delegate->audioStreamStateChanged(m_state);
    }
}

/* This is called by audio file stream parser when it finds property values */
void Audio_Stream::propertyValueCallback(void *inClientData, AudioFileStreamID inAudioFileStream, AudioFileStreamPropertyID inPropertyID, UInt32 *ioFlags)
{
    AS_TRACE("%s\n", __PRETTY_FUNCTION__);
    Audio_Stream *THIS = static_cast<Audio_Stream*>(inClientData);

    if (!THIS->m_audioStreamParserRunning) {
        AS_TRACE("%s: stray callback detected!\n", __PRETTY_FUNCTION__);
        return;
    }

    THIS->m_audioQueue->handlePropertyChange(inAudioFileStream, inPropertyID, ioFlags);
}

/* This is called by audio file stream parser when it finds packets of audio */
void Audio_Stream::streamDataCallback(void *inClientData, UInt32 inNumberBytes, UInt32 inNumberPackets, const void *inInputData, AudioStreamPacketDescription *inPacketDescriptions)
{
    AS_TRACE("%s: inNumberBytes %lu, inNumberPackets %lu\n", __FUNCTION__, inNumberBytes, inNumberPackets);
    Audio_Stream *THIS = static_cast<Audio_Stream*>(inClientData);

    if (!THIS->m_audioStreamParserRunning) {
        AS_TRACE("%s: stray callback detected!\n", __PRETTY_FUNCTION__);
        return;
    }

    THIS->m_audioQueue->handleAudioPackets(inNumberBytes, inNumberPackets, inInputData, inPacketDescriptions);
}

} // namespace astreamer<commit_msg>Check the state properly<commit_after>/*
 * This file is part of the FreeStreamer project,
 * (C)Copyright 2011 Matias Muhonen <mmu@iki.fi>
 * See the file ''LICENSE'' for using the code.
 */

#include "audio_stream.h"

#include <pthread.h>

//#define AS_DEBUG 1

#if !defined (AS_DEBUG)
#define AS_TRACE(...) do {} while (0)
#else
#define AS_TRACE(...) printf(__VA_ARGS__)
#endif

namespace astreamer {

/* Create HTTP stream as Audio_Stream (this) as the delegate */
Audio_Stream::Audio_Stream(CFURLRef url) :
    m_delegate(0),
    m_httpStreamRunning(false),
    m_audioStreamParserRunning(false),
    m_state(STOPPED),
    m_httpStream(new HTTP_Stream(url, this)),
    m_audioQueue(new Audio_Queue())
{
    m_audioQueue->m_delegate = this;
}

Audio_Stream::~Audio_Stream()
{
    close();

    m_httpStream->m_delegate = 0;
    delete m_httpStream, m_httpStream = 0;

    m_audioQueue->m_delegate = 0;
    delete m_audioQueue, m_audioQueue = 0;
}

void Audio_Stream::open()
{
    if (m_httpStreamRunning) {
        AS_TRACE("%s: already running: return\n", __PRETTY_FUNCTION__);
        /* Already running */
        return;
    }

    if (m_httpStream->open()) {
        AS_TRACE("%s: HTTP stream opened, buffering...\n", __PRETTY_FUNCTION__);
        m_httpStreamRunning = true;
        setState(BUFFERING);
    } else {
        AS_TRACE("%s: failed to open the HTTP stream\n", __PRETTY_FUNCTION__);
        setState(FAILED);
    }
}

void Audio_Stream::close()
{
    /* Close the HTTP stream first so that the audio stream parser
       isn't fed with more data to parse */
    if (m_httpStreamRunning) {
        m_httpStream->close();
        m_httpStreamRunning = false;
    }

    if (m_audioStreamParserRunning) {
        if (AudioFileStreamClose(m_audioFileStream) != 0) {
            AS_TRACE("%s: AudioFileStreamClose failed\n", __PRETTY_FUNCTION__);
        }
        m_audioStreamParserRunning = false;
    }

    m_audioQueue->stop();
}

void Audio_Stream::pause()
{
    m_audioQueue->pause();
}

AudioFileTypeID Audio_Stream::audioStreamTypeFromContentType(std::string contentType)
{
    AudioFileTypeID fileTypeHint = kAudioFileAAC_ADTSType;

    if (contentType.compare("") == 0) {
        AS_TRACE("***** Unable to detect the audio stream type: missing content-type! *****\n");
        goto out;
    }

    if (contentType.compare("audio/mpeg") == 0) {
        fileTypeHint = kAudioFileMP3Type;
        AS_TRACE("kAudioFileMP3Type detected\n");
    } else if (contentType.compare("audio/x-wav") == 0) {
        fileTypeHint = kAudioFileWAVEType;
        AS_TRACE("kAudioFileWAVEType detected\n");
    } else if (contentType.compare("audio/x-aifc") == 0) {
        fileTypeHint = kAudioFileAIFCType;
        AS_TRACE("kAudioFileAIFCType detected\n");
    } else if (contentType.compare("audio/x-aiff") == 0) {
        fileTypeHint = kAudioFileAIFFType;
        AS_TRACE("kAudioFileAIFFType detected\n");
    } else if (contentType.compare("audio/x-m4a") == 0) {
        fileTypeHint = kAudioFileM4AType;
        AS_TRACE("kAudioFileM4AType detected\n");
    } else if (contentType.compare("audio/mp4") == 0) {
        fileTypeHint = kAudioFileMPEG4Type;
        AS_TRACE("kAudioFileMPEG4Type detected\n");
    } else if (contentType.compare("audio/x-caf") == 0) {
        fileTypeHint = kAudioFileCAFType;
        AS_TRACE("kAudioFileCAFType detected\n");
    } else if (contentType.compare("audio/aac") == 0 ||
               contentType.compare("audio/aacp") == 0) {
        fileTypeHint = kAudioFileAAC_ADTSType;
        AS_TRACE("kAudioFileAAC_ADTSType detected\n");
    } else {
        AS_TRACE("***** Unable to detect the audio stream type from content-type %s *****\n", contentType.c_str());
    }

out:
    return fileTypeHint;
}

void Audio_Stream::audioQueueStateChanged(Audio_Queue::State state)
{
    if (state == Audio_Queue::RUNNING) {
        setState(PLAYING);
    } else if (state == Audio_Queue::IDLE) {
        setState(STOPPED);
    }
}

void Audio_Stream::streamIsReadyRead()
{
    if (m_audioStreamParserRunning) {
        AS_TRACE("%s: parser already running!\n", __PRETTY_FUNCTION__);
        return;
    }

    /* Check if the stream's MIME type begins with audio/ */
    std::string contentType = m_httpStream->contentType();

    const char *audioContentType = "audio/";
    size_t audioContentTypeLength = strlen(audioContentType);

    if (contentType.compare(0, audioContentTypeLength, audioContentType) != 0) {
        closeAndSignalError(AS_ERR_OPEN);
        return;
    }

    /* OK, it should be an audio stream, let's try to open it */
    OSStatus result = AudioFileStreamOpen(this,
                                          propertyValueCallback,
                                          streamDataCallback,
                                          audioStreamTypeFromContentType(contentType),
                                          &m_audioFileStream);

    if (result == 0) {
        AS_TRACE("%s: audio file stream opened.\n", __PRETTY_FUNCTION__);
        m_audioStreamParserRunning = true;
    } else {
        closeAndSignalError(AS_ERR_OPEN);
    }
}

void Audio_Stream::streamHasBytesAvailable(UInt8 *data, CFIndex numBytes)
{
    AS_TRACE("%s: %lu bytes\n", __FUNCTION__, numBytes);

    if (!m_httpStreamRunning) {
        AS_TRACE("%s: stray callback detected!\n", __PRETTY_FUNCTION__);
        return;
    }

    if (m_audioStreamParserRunning) {
        OSStatus result = AudioFileStreamParseBytes(m_audioFileStream, numBytes, data, 0);
        if (result != 0) {
            AS_TRACE("%s: AudioFileStreamParseBytes error %d\n", __PRETTY_FUNCTION__, (int)result);
            closeAndSignalError(AS_ERR_STREAM_PARSE);
        }
    }
}

void Audio_Stream::streamEndEncountered()
{
    AS_TRACE("%s\n", __PRETTY_FUNCTION__);

    if (!m_httpStreamRunning) {
        AS_TRACE("%s: stray callback detected!\n", __PRETTY_FUNCTION__);
        return;
    }

    setState(END_OF_FILE);
    close();
}

void Audio_Stream::streamErrorOccurred()
{
    AS_TRACE("%s\n", __PRETTY_FUNCTION__);

    if (!m_httpStreamRunning) {
        AS_TRACE("%s: stray callback detected!\n", __PRETTY_FUNCTION__);
        return;
    }

    closeAndSignalError(AS_ERR_NETWORK);
}

void Audio_Stream::streamMetaDataAvailable(std::string metaData)
{
    if (m_delegate) {
        m_delegate->audioStreamMetaDataAvailable(metaData);
    }
}

/* private */

void Audio_Stream::closeAndSignalError(int errorCode)
{
    AS_TRACE("%s: error %i\n", __PRETTY_FUNCTION__, errorCode);

    setState(FAILED);
    close();

    if (m_delegate) {
        m_delegate->audioStreamErrorOccurred(errorCode);
    }
}

void Audio_Stream::setState(State state)
{
    if (m_state == state) {
        return;
    }

    m_state = state;

    if (m_delegate) {
        m_delegate->audioStreamStateChanged(m_state);
    }
}

/* This is called by audio file stream parser when it finds property values */
void Audio_Stream::propertyValueCallback(void *inClientData, AudioFileStreamID inAudioFileStream, AudioFileStreamPropertyID inPropertyID, UInt32 *ioFlags)
{
    AS_TRACE("%s\n", __PRETTY_FUNCTION__);
    Audio_Stream *THIS = static_cast<Audio_Stream*>(inClientData);

    if (!THIS->m_audioStreamParserRunning) {
        AS_TRACE("%s: stray callback detected!\n", __PRETTY_FUNCTION__);
        return;
    }

    THIS->m_audioQueue->handlePropertyChange(inAudioFileStream, inPropertyID, ioFlags);
}

/* This is called by audio file stream parser when it finds packets of audio */
void Audio_Stream::streamDataCallback(void *inClientData, UInt32 inNumberBytes, UInt32 inNumberPackets, const void *inInputData, AudioStreamPacketDescription *inPacketDescriptions)
{
    AS_TRACE("%s: inNumberBytes %lu, inNumberPackets %lu\n", __FUNCTION__, inNumberBytes, inNumberPackets);
    Audio_Stream *THIS = static_cast<Audio_Stream*>(inClientData);

    if (!THIS->m_audioStreamParserRunning) {
        AS_TRACE("%s: stray callback detected!\n", __PRETTY_FUNCTION__);
        return;
    }

    THIS->m_audioQueue->handleAudioPackets(inNumberBytes, inNumberPackets, inInputData, inPacketDescriptions);
}

} // namespace astreamer<|endoftext|>


<commit_before>/*
 * This file is part of the FreeStreamer project,
 * (C)Copyright 2011 Matias Muhonen <mmu@iki.fi>
 * See the file ''LICENSE'' for using the code.
 */

#include "audio_stream.h"

#include <pthread.h>

//#define AS_DEBUG 1

#if !defined (AS_DEBUG)
#define AS_TRACE(...) do {} while (0)
#else
#define AS_TRACE(...) printf(__VA_ARGS__)
#endif

namespace astreamer {

/* Create HTTP stream as Audio_Stream (this) as the delegate */
Audio_Stream::Audio_Stream() :
    m_delegate(0),
    m_httpStreamRunning(false),
    m_audioStreamParserRunning(false),
    m_state(STOPPED),
    m_httpStream(new HTTP_Stream()),
    m_audioQueue(new Audio_Queue())
{
    m_httpStream->m_delegate = this;
    m_audioQueue->m_delegate = this;
}

Audio_Stream::~Audio_Stream()
{
    close();

    m_httpStream->m_delegate = 0;
    delete m_httpStream, m_httpStream = 0;

    m_audioQueue->m_delegate = 0;
    delete m_audioQueue, m_audioQueue = 0;
}

void Audio_Stream::open()
{
    if (m_httpStreamRunning) {
        AS_TRACE("%s: already running: return\n", __PRETTY_FUNCTION__);
        return;
    }

    if (m_httpStream->open()) {
        AS_TRACE("%s: HTTP stream opened, buffering...\n", __PRETTY_FUNCTION__);
        m_httpStreamRunning = true;
        setState(BUFFERING);
    } else {
        AS_TRACE("%s: failed to open the HTTP stream\n", __PRETTY_FUNCTION__);
        setState(FAILED);
    }
}

void Audio_Stream::close()
{
    AS_TRACE("%s: enter\n", __PRETTY_FUNCTION__);

    /* Close the HTTP stream first so that the audio stream parser
       isn't fed with more data to parse */
    if (m_httpStreamRunning) {
        m_httpStream->close();
        m_httpStreamRunning = false;
    }

    if (m_audioStreamParserRunning) {
        if (AudioFileStreamClose(m_audioFileStream) != 0) {
            AS_TRACE("%s: AudioFileStreamClose failed\n", __PRETTY_FUNCTION__);
        }
        m_audioStreamParserRunning = false;
    }

    m_audioQueue->stop();

    AS_TRACE("%s: leave\n", __PRETTY_FUNCTION__);
}

void Audio_Stream::pause()
{
    m_audioQueue->pause();
}

unsigned Audio_Stream::timePlayedInSeconds()
{
    return m_audioQueue->timePlayedInSeconds();
}

unsigned Audio_Stream::durationInSeconds()
{
    unsigned duration = 0;
    unsigned bitrate = m_audioQueue->bitrate();

    if (bitrate == 0) {
        goto out;
    }

    duration = m_httpStream->contentLength() / (bitrate * 0.125);

out:
    return duration;
}

void Audio_Stream::setUrl(CFURLRef url)
{
    m_httpStream->setUrl(url);
}

AudioFileTypeID Audio_Stream::audioStreamTypeFromContentType(std::string contentType)
{
    AudioFileTypeID fileTypeHint = kAudioFileAAC_ADTSType;

    if (contentType.compare("") == 0) {
        AS_TRACE("***** Unable to detect the audio stream type: missing content-type! *****\n");
        goto out;
    }

    if (contentType.compare("audio/mpeg") == 0) {
        fileTypeHint = kAudioFileMP3Type;
        AS_TRACE("kAudioFileMP3Type detected\n");
    } else if (contentType.compare("audio/x-wav") == 0) {
        fileTypeHint = kAudioFileWAVEType;
        AS_TRACE("kAudioFileWAVEType detected\n");
    } else if (contentType.compare("audio/x-aifc") == 0) {
        fileTypeHint = kAudioFileAIFCType;
        AS_TRACE("kAudioFileAIFCType detected\n");
    } else if (contentType.compare("audio/x-aiff") == 0) {
        fileTypeHint = kAudioFileAIFFType;
        AS_TRACE("kAudioFileAIFFType detected\n");
    } else if (contentType.compare("audio/x-m4a") == 0) {
        fileTypeHint = kAudioFileM4AType;
        AS_TRACE("kAudioFileM4AType detected\n");
    } else if (contentType.compare("audio/mp4") == 0) {
        fileTypeHint = kAudioFileMPEG4Type;
        AS_TRACE("kAudioFileMPEG4Type detected\n");
    } else if (contentType.compare("audio/x-caf") == 0) {
        fileTypeHint = kAudioFileCAFType;
        AS_TRACE("kAudioFileCAFType detected\n");
    } else if (contentType.compare("audio/aac") == 0 ||
               contentType.compare("audio/aacp") == 0) {
        fileTypeHint = kAudioFileAAC_ADTSType;
        AS_TRACE("kAudioFileAAC_ADTSType detected\n");
    } else {
        AS_TRACE("***** Unable to detect the audio stream type from content-type %s *****\n", contentType.c_str());
    }

out:
    return fileTypeHint;
}

void Audio_Stream::audioQueueStateChanged(Audio_Queue::State state)
{
    if (state == Audio_Queue::RUNNING) {
        setState(PLAYING);
    } else if (state == Audio_Queue::IDLE) {
        setState(STOPPED);
    }
}

void Audio_Stream::audioQueueBuffersEmpty()
{
    AS_TRACE("%s: enter\n", __PRETTY_FUNCTION__);

    if (m_httpStreamRunning) {
        /* Still feeding the audio queue with data,
           don't stop yet */
        return;
    }

    AS_TRACE("%s: closing the audio queue\n", __PRETTY_FUNCTION__);

    if (m_audioStreamParserRunning) {
        if (AudioFileStreamClose(m_audioFileStream) != 0) {
            AS_TRACE("%s: AudioFileStreamClose failed\n", __PRETTY_FUNCTION__);
        }
        m_audioStreamParserRunning = false;
    }

    // Keep the audio queue running until it has finished playing
    m_audioQueue->stop(false);

    AS_TRACE("%s: leave\n", __PRETTY_FUNCTION__);
}

void Audio_Stream::audioQueueOverflow()
{
    m_httpStream->setScheduledInRunLoop(false);
}

void Audio_Stream::audioQueueUnderflow()
{
    m_httpStream->setScheduledInRunLoop(true);
}

void Audio_Stream::streamIsReadyRead()
{
    if (m_audioStreamParserRunning) {
        AS_TRACE("%s: parser already running!\n", __PRETTY_FUNCTION__);
        return;
    }

    /* Check if the stream's MIME type begins with audio/ */
    std::string contentType = m_httpStream->contentType();

    const char *audioContentType = "audio/";
    size_t audioContentTypeLength = strlen(audioContentType);

    if (contentType.compare(0, audioContentTypeLength, audioContentType) != 0) {
        closeAndSignalError(AS_ERR_OPEN);
        return;
    }

    /* OK, it should be an audio stream, let's try to open it */
    OSStatus result = AudioFileStreamOpen(this,
                                          propertyValueCallback,
                                          streamDataCallback,
                                          audioStreamTypeFromContentType(contentType),
                                          &m_audioFileStream);

    if (result == 0) {
        AS_TRACE("%s: audio file stream opened.\n", __PRETTY_FUNCTION__);
        m_audioStreamParserRunning = true;
    } else {
        closeAndSignalError(AS_ERR_OPEN);
    }
}

void Audio_Stream::streamHasBytesAvailable(UInt8 *data, CFIndex numBytes)
{
    AS_TRACE("%s: %lu bytes\n", __FUNCTION__, numBytes);

    if (!m_httpStreamRunning) {
        AS_TRACE("%s: stray callback detected!\n", __PRETTY_FUNCTION__);
        return;
    }

    if (m_audioStreamParserRunning) {
        OSStatus result = AudioFileStreamParseBytes(m_audioFileStream, numBytes, data, 0);
        if (result != 0) {
            AS_TRACE("%s: AudioFileStreamParseBytes error %d\n", __PRETTY_FUNCTION__, (int)result);
            closeAndSignalError(AS_ERR_STREAM_PARSE);
        }
    }
}

void Audio_Stream::streamEndEncountered()
{
    AS_TRACE("%s\n", __PRETTY_FUNCTION__);

    if (!m_httpStreamRunning) {
        AS_TRACE("%s: stray callback detected!\n", __PRETTY_FUNCTION__);
        return;
    }

    setState(END_OF_FILE);

    m_httpStream->close();
    m_httpStreamRunning = false;
}

void Audio_Stream::streamErrorOccurred()
{
    AS_TRACE("%s\n", __PRETTY_FUNCTION__);

    if (!m_httpStreamRunning) {
        AS_TRACE("%s: stray callback detected!\n", __PRETTY_FUNCTION__);
        return;
    }

    closeAndSignalError(AS_ERR_NETWORK);
}

void Audio_Stream::streamMetaDataAvailable(std::string metaData)
{
    if (m_delegate) {
        m_delegate->audioStreamMetaDataAvailable(metaData);
    }
}

/* private */

void Audio_Stream::closeAndSignalError(int errorCode)
{
    AS_TRACE("%s: error %i\n", __PRETTY_FUNCTION__, errorCode);

    setState(FAILED);
    close();

    if (m_delegate) {
        m_delegate->audioStreamErrorOccurred(errorCode);
    }
}

void Audio_Stream::setState(State state)
{
    if (m_state == state) {
        return;
    }

    m_state = state;

    if (m_delegate) {
        m_delegate->audioStreamStateChanged(m_state);
    }
}

/* This is called by audio file stream parser when it finds property values */
void Audio_Stream::propertyValueCallback(void *inClientData, AudioFileStreamID inAudioFileStream, AudioFileStreamPropertyID inPropertyID, UInt32 *ioFlags)
{
    AS_TRACE("%s\n", __PRETTY_FUNCTION__);
    Audio_Stream *THIS = static_cast<Audio_Stream*>(inClientData);

    if (!THIS->m_audioStreamParserRunning) {
        AS_TRACE("%s: stray callback detected!\n", __PRETTY_FUNCTION__);
        return;
    }

    THIS->m_audioQueue->handlePropertyChange(inAudioFileStream, inPropertyID, ioFlags);
}

/* This is called by audio file stream parser when it finds packets of audio */
void Audio_Stream::streamDataCallback(void *inClientData, UInt32 inNumberBytes, UInt32 inNumberPackets, const void *inInputData, AudioStreamPacketDescription *inPacketDescriptions)
{
    AS_TRACE("%s: inNumberBytes %lu, inNumberPackets %lu\n", __FUNCTION__, inNumberBytes, inNumberPackets);
    Audio_Stream *THIS = static_cast<Audio_Stream*>(inClientData);

    if (!THIS->m_audioStreamParserRunning) {
        AS_TRACE("%s: stray callback detected!\n", __PRETTY_FUNCTION__);
        return;
    }

    THIS->m_audioQueue->handleAudioPackets(inNumberBytes, inNumberPackets, inInputData, inPacketDescriptions);
}

} // namespace astreamer<commit_msg>Remove an unneeded include.<commit_after>/*
 * This file is part of the FreeStreamer project,
 * (C)Copyright 2011 Matias Muhonen <mmu@iki.fi>
 * See the file ''LICENSE'' for using the code.
 */

#include "audio_stream.h"

//#define AS_DEBUG 1

#if !defined (AS_DEBUG)
#define AS_TRACE(...) do {} while (0)
#else
#define AS_TRACE(...) printf(__VA_ARGS__)
#endif

namespace astreamer {

/* Create HTTP stream as Audio_Stream (this) as the delegate */
Audio_Stream::Audio_Stream() :
    m_delegate(0),
    m_httpStreamRunning(false),
    m_audioStreamParserRunning(false),
    m_state(STOPPED),
    m_httpStream(new HTTP_Stream()),
    m_audioQueue(new Audio_Queue())
{
    m_httpStream->m_delegate = this;
    m_audioQueue->m_delegate = this;
}

Audio_Stream::~Audio_Stream()
{
    close();

    m_httpStream->m_delegate = 0;
    delete m_httpStream, m_httpStream = 0;

    m_audioQueue->m_delegate = 0;
    delete m_audioQueue, m_audioQueue = 0;
}

void Audio_Stream::open()
{
    if (m_httpStreamRunning) {
        AS_TRACE("%s: already running: return\n", __PRETTY_FUNCTION__);
        return;
    }

    if (m_httpStream->open()) {
        AS_TRACE("%s: HTTP stream opened, buffering...\n", __PRETTY_FUNCTION__);
        m_httpStreamRunning = true;
        setState(BUFFERING);
    } else {
        AS_TRACE("%s: failed to open the HTTP stream\n", __PRETTY_FUNCTION__);
        setState(FAILED);
    }
}

void Audio_Stream::close()
{
    AS_TRACE("%s: enter\n", __PRETTY_FUNCTION__);

    /* Close the HTTP stream first so that the audio stream parser
       isn't fed with more data to parse */
    if (m_httpStreamRunning) {
        m_httpStream->close();
        m_httpStreamRunning = false;
    }

    if (m_audioStreamParserRunning) {
        if (AudioFileStreamClose(m_audioFileStream) != 0) {
            AS_TRACE("%s: AudioFileStreamClose failed\n", __PRETTY_FUNCTION__);
        }
        m_audioStreamParserRunning = false;
    }

    m_audioQueue->stop();

    AS_TRACE("%s: leave\n", __PRETTY_FUNCTION__);
}

void Audio_Stream::pause()
{
    m_audioQueue->pause();
}

unsigned Audio_Stream::timePlayedInSeconds()
{
    return m_audioQueue->timePlayedInSeconds();
}

unsigned Audio_Stream::durationInSeconds()
{
    unsigned duration = 0;
    unsigned bitrate = m_audioQueue->bitrate();

    if (bitrate == 0) {
        goto out;
    }

    duration = m_httpStream->contentLength() / (bitrate * 0.125);

out:
    return duration;
}

void Audio_Stream::setUrl(CFURLRef url)
{
    m_httpStream->setUrl(url);
}

AudioFileTypeID Audio_Stream::audioStreamTypeFromContentType(std::string contentType)
{
    AudioFileTypeID fileTypeHint = kAudioFileAAC_ADTSType;

    if (contentType.compare("") == 0) {
        AS_TRACE("***** Unable to detect the audio stream type: missing content-type! *****\n");
        goto out;
    }

    if (contentType.compare("audio/mpeg") == 0) {
        fileTypeHint = kAudioFileMP3Type;
        AS_TRACE("kAudioFileMP3Type detected\n");
    } else if (contentType.compare("audio/x-wav") == 0) {
        fileTypeHint = kAudioFileWAVEType;
        AS_TRACE("kAudioFileWAVEType detected\n");
    } else if (contentType.compare("audio/x-aifc") == 0) {
        fileTypeHint = kAudioFileAIFCType;
        AS_TRACE("kAudioFileAIFCType detected\n");
    } else if (contentType.compare("audio/x-aiff") == 0) {
        fileTypeHint = kAudioFileAIFFType;
        AS_TRACE("kAudioFileAIFFType detected\n");
    } else if (contentType.compare("audio/x-m4a") == 0) {
        fileTypeHint = kAudioFileM4AType;
        AS_TRACE("kAudioFileM4AType detected\n");
    } else if (contentType.compare("audio/mp4") == 0) {
        fileTypeHint = kAudioFileMPEG4Type;
        AS_TRACE("kAudioFileMPEG4Type detected\n");
    } else if (contentType.compare("audio/x-caf") == 0) {
        fileTypeHint = kAudioFileCAFType;
        AS_TRACE("kAudioFileCAFType detected\n");
    } else if (contentType.compare("audio/aac") == 0 ||
               contentType.compare("audio/aacp") == 0) {
        fileTypeHint = kAudioFileAAC_ADTSType;
        AS_TRACE("kAudioFileAAC_ADTSType detected\n");
    } else {
        AS_TRACE("***** Unable to detect the audio stream type from content-type %s *****\n", contentType.c_str());
    }

out:
    return fileTypeHint;
}

void Audio_Stream::audioQueueStateChanged(Audio_Queue::State state)
{
    if (state == Audio_Queue::RUNNING) {
        setState(PLAYING);
    } else if (state == Audio_Queue::IDLE) {
        setState(STOPPED);
    }
}

void Audio_Stream::audioQueueBuffersEmpty()
{
    AS_TRACE("%s: enter\n", __PRETTY_FUNCTION__);

    if (m_httpStreamRunning) {
        /* Still feeding the audio queue with data,
           don't stop yet */
        return;
    }

    AS_TRACE("%s: closing the audio queue\n", __PRETTY_FUNCTION__);

    if (m_audioStreamParserRunning) {
        if (AudioFileStreamClose(m_audioFileStream) != 0) {
            AS_TRACE("%s: AudioFileStreamClose failed\n", __PRETTY_FUNCTION__);
        }
        m_audioStreamParserRunning = false;
    }

    // Keep the audio queue running until it has finished playing
    m_audioQueue->stop(false);

    AS_TRACE("%s: leave\n", __PRETTY_FUNCTION__);
}

void Audio_Stream::audioQueueOverflow()
{
    m_httpStream->setScheduledInRunLoop(false);
}

void Audio_Stream::audioQueueUnderflow()
{
    m_httpStream->setScheduledInRunLoop(true);
}

void Audio_Stream::streamIsReadyRead()
{
    if (m_audioStreamParserRunning) {
        AS_TRACE("%s: parser already running!\n", __PRETTY_FUNCTION__);
        return;
    }

    /* Check if the stream's MIME type begins with audio/ */
    std::string contentType = m_httpStream->contentType();

    const char *audioContentType = "audio/";
    size_t audioContentTypeLength = strlen(audioContentType);

    if (contentType.compare(0, audioContentTypeLength, audioContentType) != 0) {
        closeAndSignalError(AS_ERR_OPEN);
        return;
    }

    /* OK, it should be an audio stream, let's try to open it */
    OSStatus result = AudioFileStreamOpen(this,
                                          propertyValueCallback,
                                          streamDataCallback,
                                          audioStreamTypeFromContentType(contentType),
                                          &m_audioFileStream);

    if (result == 0) {
        AS_TRACE("%s: audio file stream opened.\n", __PRETTY_FUNCTION__);
        m_audioStreamParserRunning = true;
    } else {
        closeAndSignalError(AS_ERR_OPEN);
    }
}

void Audio_Stream::streamHasBytesAvailable(UInt8 *data, CFIndex numBytes)
{
    AS_TRACE("%s: %lu bytes\n", __FUNCTION__, numBytes);

    if (!m_httpStreamRunning) {
        AS_TRACE("%s: stray callback detected!\n", __PRETTY_FUNCTION__);
        return;
    }

    if (m_audioStreamParserRunning) {
        OSStatus result = AudioFileStreamParseBytes(m_audioFileStream, numBytes, data, 0);
        if (result != 0) {
            AS_TRACE("%s: AudioFileStreamParseBytes error %d\n", __PRETTY_FUNCTION__, (int)result);
            closeAndSignalError(AS_ERR_STREAM_PARSE);
        }
    }
}

void Audio_Stream::streamEndEncountered()
{
    AS_TRACE("%s\n", __PRETTY_FUNCTION__);

    if (!m_httpStreamRunning) {
        AS_TRACE("%s: stray callback detected!\n", __PRETTY_FUNCTION__);
        return;
    }

    setState(END_OF_FILE);

    m_httpStream->close();
    m_httpStreamRunning = false;
}

void Audio_Stream::streamErrorOccurred()
{
    AS_TRACE("%s\n", __PRETTY_FUNCTION__);

    if (!m_httpStreamRunning) {
        AS_TRACE("%s: stray callback detected!\n", __PRETTY_FUNCTION__);
        return;
    }

    closeAndSignalError(AS_ERR_NETWORK);
}

void Audio_Stream::streamMetaDataAvailable(std::string metaData)
{
    if (m_delegate) {
        m_delegate->audioStreamMetaDataAvailable(metaData);
    }
}

/* private */

void Audio_Stream::closeAndSignalError(int errorCode)
{
    AS_TRACE("%s: error %i\n", __PRETTY_FUNCTION__, errorCode);

    setState(FAILED);
    close();

    if (m_delegate) {
        m_delegate->audioStreamErrorOccurred(errorCode);
    }
}

void Audio_Stream::setState(State state)
{
    if (m_state == state) {
        return;
    }

    m_state = state;

    if (m_delegate) {
        m_delegate->audioStreamStateChanged(m_state);
    }
}

/* This is called by audio file stream parser when it finds property values */
void Audio_Stream::propertyValueCallback(void *inClientData, AudioFileStreamID inAudioFileStream, AudioFileStreamPropertyID inPropertyID, UInt32 *ioFlags)
{
    AS_TRACE("%s\n", __PRETTY_FUNCTION__);
    Audio_Stream *THIS = static_cast<Audio_Stream*>(inClientData);

    if (!THIS->m_audioStreamParserRunning) {
        AS_TRACE("%s: stray callback detected!\n", __PRETTY_FUNCTION__);
        return;
    }

    THIS->m_audioQueue->handlePropertyChange(inAudioFileStream, inPropertyID, ioFlags);
}

/* This is called by audio file stream parser when it finds packets of audio */
void Audio_Stream::streamDataCallback(void *inClientData, UInt32 inNumberBytes, UInt32 inNumberPackets, const void *inInputData, AudioStreamPacketDescription *inPacketDescriptions)
{
    AS_TRACE("%s: inNumberBytes %lu, inNumberPackets %lu\n", __FUNCTION__, inNumberBytes, inNumberPackets);
    Audio_Stream *THIS = static_cast<Audio_Stream*>(inClientData);

    if (!THIS->m_audioStreamParserRunning) {
        AS_TRACE("%s: stray callback detected!\n", __PRETTY_FUNCTION__);
        return;
    }

    THIS->m_audioQueue->handleAudioPackets(inNumberBytes, inNumberPackets, inInputData, inPacketDescriptions);
}

} // namespace astreamer<|endoftext|>


<commit_before>// Copyright (c) 2010-2021, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-443271.
//
// This file is part of the GLVis visualization tool and library. For more
// information and source code availability see https://glvis.org.
//
// GLVis is free software; you can redistribute it and/or modify it under the
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.

#include "sdl_windows.hpp"

#ifdef SDL_VIDEO_DRIVER_WINDOWS

#include <SDL2/SDL_syswm.h>

#include <iostream>

using namespace std;

struct SdlWindowsPlatform::Impl
{
   HANDLE signal_evt;
};

SdlWindowsPlatform::SdlWindowsPlatform()
    : m_impl(new Impl)
{
   m_impl->signal_evt = CreateEventA(nullptr, false, false, "");
   if (m_impl->signal_evt == NULL)
   {
      cerr << "Error: CreateEventA() failed with code " << GetLastError() << endl;
   }
}

SdlWindowsPlatform::~SdlWindowsPlatform()
{
   CloseHandle(m_impl->signal_evt);
}

void SdlWindowsPlatform::WaitEvent()
{
   MSG unused;
   // This call either waits for an event from Windows to be posted to the main
   // thread's message queue, or for the event object to be set by one of the
   // worker threads.
   // A timeout of 500ms is set to allow for interrupts to be pumped into the
   // SDL event queue.
   DWORD retval = MsgWaitForMultipleObjectsEx(1,
                                              &(m_impl->signal_evt),
                                              500,
                                              QS_ALLINPUT,
                                              MWMO_INPUTAVAILABLE);
   if (retval == WAIT_FAILED)
   {
      cerr << "Error: MsgWaitForMultipleObjectsEx() failed with code "
           << GetLastError() << endl;
   }
   if (ResetEvent(m_impl->signal_evt) == NULL)
   {
      cerr << "Error: ResetEvent() failed with code " << GetLastError() << endl;
   }
}

void SdlWindowsPlatform::SendEvent()
{
   if (!SetEvent(m_impl->signal_evt))
   {
      cerr << "Error: SetEvent() failed with code " << GetLastError() << endl;
   }
}

#endif // SDL_VIDEO_DRIVER_WINDOWS<commit_msg>Minor cleanup<commit_after>// Copyright (c) 2010-2021, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-443271.
//
// This file is part of the GLVis visualization tool and library. For more
// information and source code availability see https://glvis.org.
//
// GLVis is free software; you can redistribute it and/or modify it under the
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.

#include "sdl_windows.hpp"

#ifdef SDL_VIDEO_DRIVER_WINDOWS

#include <SDL2/SDL_syswm.h>

#include <iostream>

using namespace std;

struct SdlWindowsPlatform::Impl
{
   HANDLE signal_evt;
};

SdlWindowsPlatform::SdlWindowsPlatform()
    : m_impl(new Impl)
{
   m_impl->signal_evt = CreateEventA(nullptr, false, false, "");
   if (m_impl->signal_evt == NULL)
   {
      cerr << "Error: CreateEventA() failed with code " << GetLastError() << endl;
   }
}

SdlWindowsPlatform::~SdlWindowsPlatform()
{
   CloseHandle(m_impl->signal_evt);
}

void SdlWindowsPlatform::WaitEvent()
{
   // This call either waits for an event from Windows to be posted to the main
   // thread's message queue, or for the event object to be set by one of the
   // worker threads.
   // A timeout of 500ms is set to allow for interrupts to be pumped into the
   // SDL event queue.
   DWORD retval = MsgWaitForMultipleObjectsEx(1,
                                              &(m_impl->signal_evt),
                                              500,
                                              QS_ALLINPUT,
                                              MWMO_INPUTAVAILABLE);
   if (retval == WAIT_FAILED)
   {
      cerr << "Error: MsgWaitForMultipleObjectsEx() failed with code "
           << GetLastError() << endl;
   }
   if (ResetEvent(m_impl->signal_evt) == NULL)
   {
      cerr << "Error: ResetEvent() failed with code " << GetLastError() << endl;
   }
}

void SdlWindowsPlatform::SendEvent()
{
   if (SetEvent(m_impl->signal_evt) == NULL)
   {
      cerr << "Error: SetEvent() failed with code " << GetLastError() << endl;
   }
}

#endif // SDL_VIDEO_DRIVER_WINDOWS
<|endoftext|>


<commit_before><commit_msg>cleanups<commit_after><|endoftext|>


<commit_before>#include "ModuleLoader.h"
#include "Globals.h"
#include "Application.h"
#include "ModuleInput.h"
#include "ModuleGeometries.h"
#include "WindowManager.h"
#include "ModuleInspector.h"
#include "ModuleHierarchy.h"
#include "ModuleCamera3D.h"
#include "_Model.h"
#include "Assimp/include/cimport.h"
#include "Assimp/include/scene.h"
#include "Assimp/include/postprocess.h"
#include "Assimp/include/cfileio.h"
#include <string>

#pragma comment(lib, "Assimp/libx86/assimp.lib")

ModuleLoader::ModuleLoader(bool start_enabled): Module(start_enabled)
{
	Start_enabled = true;
	Update_enabled = true;

	name = "FBX Loader";
}

ModuleLoader::~ModuleLoader()
{
}

bool ModuleLoader::Start()
{

	struct aiLogStream stream;
	stream = aiGetPredefinedLogStream(aiDefaultLogStream_DEBUGGER, nullptr);
	aiAttachLogStream(&stream);
	return true;
}

update_status ModuleLoader::Update(float dt)
{
	perf_timer.Start();

	//TODO -> place it in postUpdate method
	if (App->input->dropped)
	{
		dropped_Filetype = CheckFileType(App->input->dropped_filedir);

		switch (dropped_Filetype)
		{
		case F_MODEL:
		{
			LOG("IMPORTING MODEL, File Path: %s", App->input->dropped_filedir);
			LoadMesh(App->input->dropped_filedir);

			//Fix Camera to model ------------------------
			App->camera->LookAndMoveToObject();
			// ---------------------------------

			SDL_free(App->input->dropped_filedir);

			break;
		}
		case F_TEXTURE:
		{
			LOG("IMPORTING TEXTURE, File Path: %s", App->input->dropped_filedir);

			//Check if there's a Geometry to apply the dropped texture
			if (App->geometry_manager->geometry != nullptr)
			{
				/*Delete the previous textures to apply the new one*/
				((_Model*)(App->geometry_manager->geometry))->ClearTexture(mesh_index, tex_index, tex_id);
				((_Model*)(App->geometry_manager->geometry))->SetTexture(App->input->dropped_filedir, mesh_index, tex_index, tex_id);

			}
			else
			{
				LOG("FAIL LOADING TEXTURE: No model to apply it");
			}

			//Fix Camera to model ------------------------
			App->camera->LookAndMoveToObject();
			// ---------------------------------

			SDL_free(App->input->dropped_filedir);

			mesh_index = -1;
			tex_index = -1;

			break;
		}
		case F_UNKNOWN:
		{
			SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "UNKNOWN file type dropped on window",
				App->input->dropped_filedir, App->window->window);
			LOG("UNKNOWN FILE TYPE, File Path: %s", App->input->dropped_filedir);

			break;
		}

		default:
			break;

		}

		App->input->dropped = false;
	}

	Update_t = perf_timer.ReadMs();

	return UPDATE_CONTINUE;
}

//update_status ModuleFBXLoader::postUpdate(float dt)
//{
//	if (App->input->dropped)
//	{
//		LoadMesh(App->input->dropped_filedir);
//		App->input->dropped = false;
//	}
//
//	return UPDATE_CONTINUE;
//}

bool ModuleLoader::CleanUp()
{
	aiDetachAllLogStreams();
	return true;
}

FileType ModuleLoader::CheckFileType(char * filedir)
{
	if (filedir != nullptr)
	{
		std::string file_type;
		std::string path(filedir);

		size_t extension_pos = path.find_last_of(".");

		file_type = path.substr(extension_pos + 1);

		//Set lowercase the extension to normalize it
		for (std::string::iterator it = file_type.begin(); it != file_type.end(); it++)
		{
			*it = tolower(*it);
		}

		if (file_type == "png" || file_type == "jpg" || file_type == "dds")
		{
			return F_TEXTURE;
		}
		else if (file_type == "fbx" || file_type == "obj")
		{
			return F_MODEL;
		}
		else
		{
			return F_UNKNOWN;
		}
	}
}

BaseGeometry* ModuleLoader::LoadMesh(const char* filename)
{
	if (App->geometry_manager->geometry != nullptr)
	{
		App->geometry_manager->geometry->Clear();
		RELEASE(App->geometry_manager->geometry);
	}

	_Model* new_model = new _Model(filename, P_MODEL, App->renderer3D->wireframe);

	((Inspector*)App->gui->winManager[INSPECTOR])->model_loaded = true;
	((Inspector*)App->gui->winManager[INSPECTOR])->SetInfo(new_model);
	((Hierarchy*)App->gui->winManager[HIERARCHY])->SetName(new_model);

	App->geometry_manager->geometry = new_model;

	return m;
}

void ModuleLoader::SetInfoToLoadTex(int m, int t, int t_id)
{
	mesh_index = m;
	tex_index = t;
	tex_id = t_id;
}

<commit_msg>Fixed ModuleLoader<commit_after>#include "ModuleLoader.h"
#include "Globals.h"
#include "Application.h"
#include "ModuleInput.h"
#include "ModuleGeometries.h"
#include "WindowManager.h"
#include "ModuleInspector.h"
#include "ModuleHierarchy.h"
#include "ModuleCamera3D.h"
#include "_Model.h"
#include "Assimp/include/cimport.h"
#include "Assimp/include/scene.h"
#include "Assimp/include/postprocess.h"
#include "Assimp/include/cfileio.h"
#include <string>

#pragma comment(lib, "Assimp/libx86/assimp.lib")

ModuleLoader::ModuleLoader(bool start_enabled): Module(start_enabled)
{
	Start_enabled = true;
	Update_enabled = true;

	name = "FBX Loader";
}

ModuleLoader::~ModuleLoader()
{
}

bool ModuleLoader::Start()
{

	struct aiLogStream stream;
	stream = aiGetPredefinedLogStream(aiDefaultLogStream_DEBUGGER, nullptr);
	aiAttachLogStream(&stream);
	return true;
}

update_status ModuleLoader::Update(float dt)
{
	perf_timer.Start();

	//TODO -> place it in postUpdate method
	if (App->input->dropped)
	{
		dropped_Filetype = CheckFileType(App->input->dropped_filedir);

		switch (dropped_Filetype)
		{
		case F_MODEL:
		{
			LOG("IMPORTING MODEL, File Path: %s", App->input->dropped_filedir);
			LoadMesh(App->input->dropped_filedir);

			//Fix Camera to model ------------------------
			App->camera->LookAndMoveToObject();
			// ---------------------------------

			SDL_free(App->input->dropped_filedir);

			break;
		}
		case F_TEXTURE:
		{
			LOG("IMPORTING TEXTURE, File Path: %s", App->input->dropped_filedir);

			//Check if there's a Geometry to apply the dropped texture
			if (App->geometry_manager->geometry != nullptr)
			{
				/*Delete the previous textures to apply the new one*/
				((_Model*)(App->geometry_manager->geometry))->ClearTexture(mesh_index, tex_index, tex_id);
				((_Model*)(App->geometry_manager->geometry))->SetTexture(App->input->dropped_filedir, mesh_index, tex_index, tex_id);

			}
			else
			{
				LOG("FAIL LOADING TEXTURE: No model to apply it");
			}

			//Fix Camera to model ------------------------
			App->camera->LookAndMoveToObject();
			// ---------------------------------

			SDL_free(App->input->dropped_filedir);

			mesh_index = -1;
			tex_index = -1;

			break;
		}
		case F_UNKNOWN:
		{
			SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "UNKNOWN file type dropped on window",
				App->input->dropped_filedir, App->window->window);
			LOG("UNKNOWN FILE TYPE, File Path: %s", App->input->dropped_filedir);

			break;
		}

		default:
			break;

		}

		App->input->dropped = false;
	}

	Update_t = perf_timer.ReadMs();

	return UPDATE_CONTINUE;
}

//update_status ModuleFBXLoader::postUpdate(float dt)
//{
//	if (App->input->dropped)
//	{
//		LoadMesh(App->input->dropped_filedir);
//		App->input->dropped = false;
//	}
//
//	return UPDATE_CONTINUE;
//}

bool ModuleLoader::CleanUp()
{
	aiDetachAllLogStreams();
	return true;
}

FileType ModuleLoader::CheckFileType(char * filedir)
{
	if (filedir != nullptr)
	{
		std::string file_type;
		std::string path(filedir);

		size_t extension_pos = path.find_last_of(".");

		file_type = path.substr(extension_pos + 1);

		//Set lowercase the extension to normalize it
		for (std::string::iterator it = file_type.begin(); it != file_type.end(); it++)
		{
			*it = tolower(*it);
		}

		if (file_type == "png" || file_type == "jpg" || file_type == "dds")
		{
			return F_TEXTURE;
		}
		else if (file_type == "fbx" || file_type == "obj")
		{
			return F_MODEL;
		}
		else
		{
			return F_UNKNOWN;
		}
	}
}

BaseGeometry* ModuleLoader::LoadMesh(const char* filename)
{
	if (App->geometry_manager->geometry != nullptr)
	{
		App->geometry_manager->geometry->Clear();
		RELEASE(App->geometry_manager->geometry);
	}

	_Model* new_model = new _Model(filename, P_MODEL, App->renderer3D->wireframe);

	if (new_model->loaded_success)
	{
		((Inspector*)App->gui->winManager[INSPECTOR])->model_loaded = true;
		((Inspector*)App->gui->winManager[INSPECTOR])->SetInfo(new_model);
		((Hierarchy*)App->gui->winManager[HIERARCHY])->SetName(new_model);

		App->geometry_manager->geometry = new_model;
	}
	else
	{
		new_model->Clear();
		RELEASE(new_model);
	}

	return m;
}

void ModuleLoader::SetInfoToLoadTex(int m, int t, int t_id)
{
	mesh_index = m;
	tex_index = t;
	tex_id = t_id;
}

<|endoftext|>