<commit_before>#include <test/TestBase.h>

#include <common/Trace.h>

//#undef TRC_LEVEL
//#define TRC_LEVEL TRC_L_DEB

#define HandleAssertFail(exp, file, line, msg)                                 \
  ((void)fprintf(stderr, "%s:%u: failed assertion `%s': \"%s\"\n", file, line, \
                 exp, msg),                                                    \
   abort())

// for now the asserts are always on!
// TODO make the asserts primarity for DEBUG and google test.
#define RelAssertMsg(exp, msg)                                                 \
  (__builtin_expect(!(exp), 0)                                                 \
       ? HandleAssertFail(#exp, __FILE__, __LINE__, msg)                       \
       : (void)0)

template <size_t kSlotBytes_, size_t kNumSlots,
          size_t kSlotAlignment = kSlotBytes_, size_t kStartAlignment_ = 16,
          bool kDebug = true>
class FixedSizePool {
public:
  static const size_t kSlotBytes = std::max(kSlotBytes_, kSlotAlignment);
  static const size_t kStartAlignment =
      std::max(kSlotAlignment, kStartAlignment_);

  static const unsigned char kMemDeletedPat = 0xED;
  static const unsigned char kMemAllocatedPat = 0xCD;
  // static const uint32_t kInvalidIndex = 0xFFFFFFFF;

  uint32_t m_NumSlotsUsed;
  uint32_t m_NextFreeSlot[kNumSlots];
  alignas(kStartAlignment) unsigned char m_PoolBytes[kSlotBytes * kNumSlots];

  FixedSizePool() {

    XTRACE(MAIN, DEB,
           "FixedSizePool: kSlotBytes %u, kNumSlots %u, kSlotAlignment %u, "
           "kStartAlignment %u, kDebug %u, TotalBytes %u",
           (uint32_t)kSlotBytes, (uint32_t)kNumSlots, (uint32_t)kSlotAlignment,
           (uint32_t)kStartAlignment, kDebug ? 1 : 0, (uint32_t)sizeof(*this));

    m_NumSlotsUsed = 0;
    for (size_t i = 0; i < kNumSlots; ++i) {
      m_NextFreeSlot[i] = i;
    }

    if (kDebug) {
      memset(m_PoolBytes, kMemDeletedPat, sizeof(m_PoolBytes));
    }
  }

  ~FixedSizePool() {
    RelAssertMsg(m_NumSlotsUsed == 0, "All slots in pool must be empty");

    if (kDebug) {
      // test m_NextFreeSlot indices are unique
      for (size_t testIndex = 0; testIndex < kNumSlots; ++testIndex) {
        __attribute__((unused)) bool testIndexFound = false;
        for (size_t i = 0; i < kNumSlots; ++i) {
          if (m_NextFreeSlot[i] == testIndex) {
            RelAssertMsg(!testIndexFound,
                         "Free slots must be unique. Could mean double delete");
            testIndexFound = true;
          }
        }
        RelAssertMsg(testIndexFound, "All slots must be used");
      }

      for (size_t i = 0; i < sizeof(m_PoolBytes); ++i) {
        RelAssertMsg(m_PoolBytes[i] == kMemDeletedPat,
                     "Deleted memory must have reference pattern");
      }
    }
  }

  inline void *AllocateOne() {
    RelAssertMsg(m_NumSlotsUsed < kNumSlots, "Implement fallover to malloc()");
    size_t index = m_NextFreeSlot[m_NumSlotsUsed];
    RelAssertMsg(index < kNumSlots, "Expect capacity");

    m_NumSlotsUsed++;
    unsigned char *p = m_PoolBytes + (index * kSlotBytes);
    RelAssertMsg(p + kSlotBytes <= m_PoolBytes + sizeof(m_PoolBytes),
                 "Don't go past end of capacity");

    if (kDebug) {
      for (size_t i = 0; i < kSlotBytes; ++i) {
        RelAssertMsg(p[i] == kMemDeletedPat,
                     "Unused memory must have deletion pattern");
      }
      memset(p, kMemAllocatedPat, kSlotBytes);
    }

    return static_cast<void *>(p);
  }

  inline void Deallocate(void *p) {
    size_t index = ((unsigned char *)p - m_PoolBytes) / kSlotBytes;
    RelAssertMsg(index < kNumSlots, "Implement fallover to free()");

    RelAssertMsg(m_NumSlotsUsed > 0, "Pool must have content");
    --m_NumSlotsUsed;

    m_NextFreeSlot[m_NumSlotsUsed] = index;

    if (kDebug) {
      memset(p, kMemDeletedPat, kSlotBytes);
    }
  }
};

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

class FixedSizePoolTest : public TestBase {
public:
};

TEST_F(FixedSizePoolTest, Small_Empty) {
  FixedSizePool<8, 1> pool;

  ASSERT_TRUE(pool.m_NumSlotsUsed == 0);
}

TEST_F(FixedSizePoolTest, Small_1) {
  FixedSizePool<8, 1> pool;

  void *mem = pool.AllocateOne();

  ASSERT_TRUE(pool.m_NumSlotsUsed == 1);
  ASSERT_TRUE(mem >= (void *)pool.m_PoolBytes);
  ASSERT_TRUE(mem < (void *)(pool.m_PoolBytes + sizeof(pool.m_PoolBytes)));

  pool.Deallocate(mem);
}

TEST_F(FixedSizePoolTest, Small_1_NewlyAllocatedPattern) {
  FixedSizePool<8, 1> pool;
  unsigned char *mem = (unsigned char *)pool.AllocateOne();
  for (size_t i = 0; i < pool.kSlotBytes; ++i) {
    ASSERT_TRUE(mem[i] == pool.kMemAllocatedPat);
  }
  pool.Deallocate(mem);
}

TEST_F(FixedSizePoolTest, Small_1_Fail_DoubleFree) {
  using FixedSizePool_t = FixedSizePool<8, 2>;
  ASSERT_DEATH(
      {
        FixedSizePool_t pool;
        void *mem = pool.AllocateOne();
        pool.AllocateOne();
        pool.Deallocate(mem);
        pool.Deallocate(mem);
      },
      "Free slots must be unique. Could mean double delete");
}

TEST_F(FixedSizePoolTest, Small_1_Fail_DeallocateWrong) {
  using FixedSizePool_t = FixedSizePool<8, 1>;
  ASSERT_DEATH(
      {
        FixedSizePool_t pool;
        void *mem = pool.AllocateOne();
        pool.Deallocate(mem);
        pool.Deallocate(mem);
      },
      "Pool must have content");
}

TEST_F(FixedSizePoolTest, Small_1_Fail_NotEmpty) {
  using FixedSizePool_t = FixedSizePool<8, 1>;
  ASSERT_DEATH(
      {
        FixedSizePool_t pool;
        pool.AllocateOne();
      },
      "All slots in pool must be empty");
}

TEST_F(FixedSizePoolTest, Small_1_Fail_DirtyRefPattern) {
  using FixedSizePool_t = FixedSizePool<8, 1>;
  ASSERT_DEATH(
      {
        FixedSizePool_t pool;
        void *mem = pool.AllocateOne();
        pool.Deallocate(mem);
        *(uint32_t *)mem = 0; // dirty the kMemDeleted zone
      },
      "Deleted memory must have reference pattern");
}

TEST_F(FixedSizePoolTest, Large_1) {
  FixedSizePool<8, 1000> pool;

  void *mem = pool.AllocateOne();

  ASSERT_TRUE(pool.m_NumSlotsUsed == 1);
  ASSERT_TRUE(mem >= (void *)pool.m_PoolBytes);
  ASSERT_TRUE(mem < (void *)(pool.m_PoolBytes + sizeof(pool.m_PoolBytes)));

  pool.Deallocate(mem);
}

TEST_F(FixedSizePoolTest, Large_All) {
  FixedSizePool<8, 1000> pool;

  void *allocs[1000];
  for (uint32_t i = 0; i < 1000; ++i) {
    allocs[i] = pool.AllocateOne();

    ASSERT_TRUE(pool.m_NumSlotsUsed == i + 1);
    ASSERT_TRUE(allocs[i] >= (void *)pool.m_PoolBytes);
    ASSERT_TRUE(allocs[i] <
                (void *)(pool.m_PoolBytes + sizeof(pool.m_PoolBytes)));
  }

  for (int i = 0; i < 1000; ++i) {
    pool.Deallocate(allocs[i]);
  }
}

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

TEST_F(FixedSizePoolTest, Align_AtSame) {
  FixedSizePool<8, 2, 8> pool;

  void *mem = pool.AllocateOne();
  ASSERT_EQ(size_t(mem) % 8, 0);

  void *mem2 = pool.AllocateOne();
  ASSERT_EQ(size_t(mem2) % 8, 0);

  ASSERT_TRUE(size_t(mem2) - size_t(mem) >= 8);

  pool.Deallocate(mem);
  pool.Deallocate(mem2);
}

TEST_F(FixedSizePoolTest, Align_At64) {
  FixedSizePool<8, 2, 64> pool;

  void *mem = pool.AllocateOne();
  ASSERT_EQ(size_t(mem) % 64, 0);

  void *mem2 = pool.AllocateOne();
  ASSERT_EQ(size_t(mem2) % 64, 0);

  ASSERT_TRUE(size_t(mem2) - size_t(mem) >= 8);

  pool.Deallocate(mem);
  pool.Deallocate(mem2);
}

TEST_F(FixedSizePoolTest, Align_At2) {
  FixedSizePool<64, 2, 2> pool;

  void *mem = pool.AllocateOne();
  ASSERT_EQ(size_t(mem) % 2, 0);

  void *mem2 = pool.AllocateOne();
  ASSERT_EQ(size_t(mem2) % 2, 0);

  ASSERT_TRUE(size_t(mem2) - size_t(mem) >= 64);

  pool.Deallocate(mem);
  pool.Deallocate(mem2);
}
<commit_msg>WIP FixedSizeAllocator<commit_after>#include <test/TestBase.h>

#include <common/Trace.h>

//#undef TRC_LEVEL
//#define TRC_LEVEL TRC_L_DEB

#define HandleAssertFail(exp, file, line, msg)                                 \
  ((void)fprintf(stderr, "%s:%u: failed assertion `%s': \"%s\"\n", file, line, \
                 exp, msg),                                                    \
   abort())

// for now the asserts are always on!
// TODO make the asserts primarity for DEBUG and google test.
#define RelAssertMsg(exp, msg)                                                 \
  (__builtin_expect(!(exp), 0)                                                 \
       ? HandleAssertFail(#exp, __FILE__, __LINE__, msg)                       \
       : (void)0)

template <size_t kSlotBytes_, size_t kNumSlots,
          size_t kSlotAlignment = kSlotBytes_, size_t kStartAlignment_ = 16,
          bool kDebug = true>
class FixedSizePool {
public:
  static const size_t kSlotBytes = std::max(kSlotBytes_, kSlotAlignment);
  static const size_t kStartAlignment =
      std::max(kSlotAlignment, kStartAlignment_);

  static const unsigned char kMemDeletedPat = 0xED;
  static const unsigned char kMemAllocatedPat = 0xCD;
  // static const uint32_t kInvalidIndex = 0xFFFFFFFF;

  uint32_t m_NumSlotsUsed;
  uint32_t m_NextFreeSlot[kNumSlots];
  alignas(kStartAlignment) unsigned char m_PoolBytes[kSlotBytes * kNumSlots];

  FixedSizePool() {

    XTRACE(MAIN, DEB,
           "FixedSizePool: kSlotBytes %u, kNumSlots %u, kSlotAlignment %u, "
           "kStartAlignment %u, kDebug %u, TotalBytes %u",
           (uint32_t)kSlotBytes, (uint32_t)kNumSlots, (uint32_t)kSlotAlignment,
           (uint32_t)kStartAlignment, kDebug ? 1 : 0, (uint32_t)sizeof(*this));

    m_NumSlotsUsed = 0;
    for (size_t i = 0; i < kNumSlots; ++i) {
      m_NextFreeSlot[i] = i;
    }

    if (kDebug) {
      memset(m_PoolBytes, kMemDeletedPat, sizeof(m_PoolBytes));
    }
  }

  ~FixedSizePool() {
    RelAssertMsg(m_NumSlotsUsed == 0, "All slots in pool must be empty");

    if (kDebug) {
      // test m_NextFreeSlot indices are unique
      for (size_t testIndex = 0; testIndex < kNumSlots; ++testIndex) {
        __attribute__((unused)) bool testIndexFound = false;
        for (size_t i = 0; i < kNumSlots; ++i) {
          if (m_NextFreeSlot[i] == testIndex) {
            RelAssertMsg(!testIndexFound,
                         "Free slots must be unique. Could mean double delete");
            testIndexFound = true;
          }
        }
        RelAssertMsg(testIndexFound, "All slots must be used");
      }

      for (size_t i = 0; i < sizeof(m_PoolBytes); ++i) {
        RelAssertMsg(m_PoolBytes[i] == kMemDeletedPat,
                     "Deleted memory must have reference pattern");
      }
    }
  }

  inline void *AllocateOne() {
    RelAssertMsg(m_NumSlotsUsed < kNumSlots, "Implement fallover to malloc()");
    size_t index = m_NextFreeSlot[m_NumSlotsUsed];
    RelAssertMsg(index < kNumSlots, "Expect capacity");

    m_NumSlotsUsed++;
    unsigned char *p = m_PoolBytes + (index * kSlotBytes);
    RelAssertMsg(p + kSlotBytes <= m_PoolBytes + sizeof(m_PoolBytes),
                 "Don't go past end of capacity");

    if (kDebug) {
      for (size_t i = 0; i < kSlotBytes; ++i) {
        RelAssertMsg(p[i] == kMemDeletedPat,
                     "Unused memory must have deletion pattern");
      }
      memset(p, kMemAllocatedPat, kSlotBytes);
    }

    return static_cast<void *>(p);
  }

  inline void Deallocate(void *p) {
    size_t index = ((unsigned char *)p - m_PoolBytes) / kSlotBytes;
    RelAssertMsg(index < kNumSlots, "Implement fallover to free()");

    RelAssertMsg(m_NumSlotsUsed > 0, "Pool must have content");
    --m_NumSlotsUsed;

    m_NextFreeSlot[m_NumSlotsUsed] = index;

    if (kDebug) {
      memset(p, kMemDeletedPat, kSlotBytes);
    }
  }
};

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

class FixedSizePoolTest : public TestBase {
public:
};

TEST_F(FixedSizePoolTest, Small_Empty) {
  FixedSizePool<8, 1> pool;

  ASSERT_TRUE(pool.m_NumSlotsUsed == 0);
}

TEST_F(FixedSizePoolTest, Small_1) {
  FixedSizePool<8, 1> pool;

  void *mem = pool.AllocateOne();

  ASSERT_TRUE(pool.m_NumSlotsUsed == 1);
  ASSERT_TRUE(mem >= (void *)pool.m_PoolBytes);
  ASSERT_TRUE(mem < (void *)(pool.m_PoolBytes + sizeof(pool.m_PoolBytes)));

  pool.Deallocate(mem);
}

TEST_F(FixedSizePoolTest, Small_1_NewlyAllocatedPattern) {
  FixedSizePool<8, 1> pool;
  unsigned char *mem = (unsigned char *)pool.AllocateOne();
  for (size_t i = 0; i < pool.kSlotBytes; ++i) {
    ASSERT_TRUE(mem[i] == pool.kMemAllocatedPat);
  }
  pool.Deallocate(mem);
}

TEST_F(FixedSizePoolTest, Small_1_Fail_DoubleFree) {
  using FixedSizePool_t = FixedSizePool<8, 2>;
  ASSERT_DEATH(
      {
        FixedSizePool_t pool;
        void *mem = pool.AllocateOne();
        pool.AllocateOne();
        pool.Deallocate(mem);
        pool.Deallocate(mem);
      },
      "Free slots must be unique. Could mean double delete");
}

TEST_F(FixedSizePoolTest, Small_1_Fail_DeallocateWrong) {
  using FixedSizePool_t = FixedSizePool<8, 1>;
  ASSERT_DEATH(
      {
        FixedSizePool_t pool;
        void *mem = pool.AllocateOne();
        pool.Deallocate(mem);
        pool.Deallocate(mem);
      },
      "Pool must have content");
}

TEST_F(FixedSizePoolTest, Small_1_Fail_NotEmpty) {
  using FixedSizePool_t = FixedSizePool<8, 1>;
  ASSERT_DEATH(
      {
        FixedSizePool_t pool;
        pool.AllocateOne();
      },
      "All slots in pool must be empty");
}

TEST_F(FixedSizePoolTest, Small_1_Fail_DirtyRefPattern) {
  using FixedSizePool_t = FixedSizePool<8, 1>;
  ASSERT_DEATH(
      {
        FixedSizePool_t pool;
        void *mem = pool.AllocateOne();
        pool.Deallocate(mem);
        *(uint32_t *)mem = 0; // dirty the kMemDeleted zone
      },
      "Deleted memory must have reference pattern");
}

TEST_F(FixedSizePoolTest, Large_1) {
  FixedSizePool<8, 1000> pool;

  void *mem = pool.AllocateOne();

  ASSERT_TRUE(pool.m_NumSlotsUsed == 1);
  ASSERT_TRUE(mem >= (void *)pool.m_PoolBytes);
  ASSERT_TRUE(mem < (void *)(pool.m_PoolBytes + sizeof(pool.m_PoolBytes)));

  pool.Deallocate(mem);
}

TEST_F(FixedSizePoolTest, Large_All) {
  FixedSizePool<8, 1000> pool;

  void *allocs[1000];
  for (uint32_t i = 0; i < 1000; ++i) {
    allocs[i] = pool.AllocateOne();

    ASSERT_TRUE(pool.m_NumSlotsUsed == i + 1);
    ASSERT_TRUE(allocs[i] >= (void *)pool.m_PoolBytes);
    ASSERT_TRUE(allocs[i] <
                (void *)(pool.m_PoolBytes + sizeof(pool.m_PoolBytes)));
  }

  for (int i = 0; i < 1000; ++i) {
    pool.Deallocate(allocs[i]);
  }
}

TEST_F(FixedSizePoolTest, Align_AtSame) {
  FixedSizePool<8, 2, 8> pool;

  void *mem = pool.AllocateOne();
  ASSERT_EQ(size_t(mem) % 8, 0);

  void *mem2 = pool.AllocateOne();
  ASSERT_EQ(size_t(mem2) % 8, 0);

  ASSERT_TRUE(size_t(mem2) - size_t(mem) >= 8);

  pool.Deallocate(mem);
  pool.Deallocate(mem2);
}

TEST_F(FixedSizePoolTest, Align_At64) {
  FixedSizePool<8, 2, 64> pool;

  void *mem = pool.AllocateOne();
  ASSERT_EQ(size_t(mem) % 64, 0);

  void *mem2 = pool.AllocateOne();
  ASSERT_EQ(size_t(mem2) % 64, 0);

  ASSERT_TRUE(size_t(mem2) - size_t(mem) >= 8);

  pool.Deallocate(mem);
  pool.Deallocate(mem2);
}

TEST_F(FixedSizePoolTest, Align_At2) {
  FixedSizePool<64, 2, 2> pool;

  void *mem = pool.AllocateOne();
  ASSERT_EQ(size_t(mem) % 2, 0);

  void *mem2 = pool.AllocateOne();
  ASSERT_EQ(size_t(mem2) % 2, 0);

  ASSERT_TRUE(size_t(mem2) - size_t(mem) >= 64);

  pool.Deallocate(mem);
  pool.Deallocate(mem2);
}

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

template <class T, size_t kTotalBytes, size_t kObjectsPerSlot>
struct FixedSizeAllocator {
  typedef T value_type;

  // enum : size_t { kObjectsPerSlot = 16 };
  enum : size_t { kSlotBytes = sizeof(T) * kObjectsPerSlot };
  enum : size_t { kNumSlots = kTotalBytes / kSlotBytes };

  static_assert(kTotalBytes >= kSlotBytes,
                "FixedSizeAllocator must have enough bytes for one slot. Is "
                "kObjectsPerSlot sensible?");

  FixedSizePool<kSlotBytes, kNumSlots, alignof(T), 16, true> m_Pool;

  FixedSizeAllocator() {
    XTRACE(MAIN, DEB, "FixedSizeAllocator: kTotalBytes %u",
           (uint32_t)kTotalBytes);
  }

  template <class U, size_t U_sz, size_t U_num>
  constexpr FixedSizeAllocator(const FixedSizeAllocator<U, U_sz, U_num> &) noexcept {}

  T *allocate(std::size_t n) {
    if (sizeof(T) * n <= m_Pool.kSlotBytes)
      return (T *)m_Pool.AllocateOne();

    XTRACE(MAIN, CRI,
           "No pool for alloc: FixedSizeAllocator %u objs, %u bytes, %u "
           "maxBytes",
           n, sizeof(T) * n, m_Pool.kSlotBytes);
    RelAssertMsg(0, "No pool for alloc");
    // throw std::bad_alloc();
    return NULL;
  }

  void deallocate(T *p, std::size_t) noexcept { m_Pool.Deallocate(p); }
};

template <class T, size_t T_sz, size_t T_num, class U, size_t U_sz, size_t U_num>
bool operator==(const FixedSizeAllocator<T, T_sz, T_num> &,
                const FixedSizeAllocator<U, U_sz, U_num> &) {
  return true;
}
template <class T, size_t T_sz, size_t T_num, class U, size_t U_sz, size_t U_num>
bool operator!=(const FixedSizeAllocator<T, T_sz, T_num> &,
                const FixedSizeAllocator<U, U_sz, U_num> &) {
  return false;
}

class FixedSizeAllocatorTest : public TestBase {
public:
};

TEST_F(FixedSizeAllocatorTest, Small_Empty) {
  FixedSizeAllocator<int, sizeof(int) * 1, 1> alloc;
}

TEST_F(FixedSizeAllocatorTest, Small_1) {
  std::vector<int, FixedSizeAllocator<int, sizeof(int) * 1, 1>> v;
  v.push_back(1);
  ASSERT_TRUE(v[0] == 1);
}

TEST_F(FixedSizeAllocatorTest, Small_Overflow) {
  using vecType = std::vector<int, FixedSizeAllocator<int, sizeof(int) * 1, 1>>;
  ASSERT_DEATH(
      {
        vecType v;
        v.push_back(1);
        v.push_back(1);
      },
      ""); // this gives a segfault
}

TEST_F(FixedSizeAllocatorTest, Small_2) {
  std::vector<int, FixedSizeAllocator<int, sizeof(int) * 2, 2>> v;
  v.reserve(2);
  v.push_back(1);
  v.push_back(2);
  ASSERT_TRUE(v[0] == 1);
  ASSERT_TRUE(v[1] == 2);
}
<|endoftext|>


<commit_before>/*
    cryptographyguiclient.cpp

    Copyright (c) 2004 by Olivier Goffart        <ogoffart @ kde.org>

    *************************************************************************
    *                                                                       *
    * 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.                                   *
    *                                                                       *
    *************************************************************************
*/
#include "cryptographyguiclient.h"
#include "cryptographyplugin.h"

#include "kopetemetacontact.h"
#include "kopetecontact.h"
#include "kopetechatsession.h"
#include "kopeteview.h"

#include <kaction.h>
#include <ktoggleaction.h>
#include <kconfig.h>
#include <klocale.h>
#include <kgenericfactory.h>
#include <kicon.h>
#include <kmessagebox.h>

#include <QList>

class CryptographyPlugin;

CryptographyGUIClient::CryptographyGUIClient(Kopete::ChatSession *parent )
 : QObject(parent) , KXMLGUIClient(parent)
{
	if(!parent || parent->members().isEmpty())
	{
		deleteLater(); //we refuse to build this client, it is based on wrong parametters
		return;
	}

	QList<Kopete::Contact*> mb=parent->members();
	Kopete::MetaContact *first=mb.first()->metaContact();

	if( !parent || parent->members().isEmpty() )
	{
		deleteLater(); //we refuse to build this client, it is based on wrong parameters
		return;
	}

	bool wantCrypto=true, keysAvailable=true;

	foreach( Kopete::Contact *c , parent->members() )
	{
		Kopete::MetaContact *mc=c->metaContact();
		if(!mc)
		{
			deleteLater();
			return;
		}
		if( mc->pluginData( CryptographyPlugin::plugin(), "encrypt_messages"  ) == "off" )
			wantCrypto = false;
		if( mc->pluginData( CryptographyPlugin::plugin(), "gpgKey" ).isEmpty() )
			keysAvailable = false;
	}

	setInstance( KGenericFactory<CryptographyPlugin>::instance() );

	m_action=new KToggleAction( KIcon("encrypted"), i18n("Encrypt Messages" ), actionCollection() , "cryptographyToggle" );
	m_action->setChecked( first->pluginData( CryptographyPlugin::plugin() , "encrypt_messages") != QString::fromLatin1("off") ) ;
	connect( m_action, SIGNAL(triggered(bool)), this, SLOT(slotToggled()) );

	setXMLFile("cryptographychatui.rc");
}

CryptographyGUIClient::~CryptographyGUIClient()
{}

void CryptographyGUIClient::slotToggled()
{
	Kopete::ChatSession *csn = static_cast<Kopete::ChatSession *>( parent() );
	QStringList keyless;

	Kopete::MetaContact *first=0L;
	foreach( Kopete::Contact * c , csn->members() )
	{
		Kopete::MetaContact *mc = c->metaContact();
		if(!mc)
			continue;

		if(!first)
			first=mc;

		if( mc->pluginData( CryptographyPlugin::plugin(), "gpgKey" ).isEmpty() )
			keyless.append(mc->displayName());
	}

	if( m_action->isChecked() && !keyless.isEmpty() )
	{
		QWidget *w = 0;
		if ( csn->view() )
			w = csn->view()->mainWidget();

		KMessageBox::sorry( w,
							i18np("To send encrypted messages to %1, you still need to select a public key for this contact.", "To send encrypted messages to them, you still need to select a public key for each of these contacts:\n%1", keyless.count() , keyless.join( "\n" ) ),
							i18np( "Missing public key", "Missing public keys", keyless.count() ) );

		m_action->setChecked( false );
	}

	first->setPluginData( CryptographyPlugin::plugin() , "encrypt_messages" ,
						  m_action->isChecked() ? "on" : "off" );

}

#include "cryptographyguiclient.moc"

<commit_msg>fix crypto action<commit_after>/*
    cryptographyguiclient.cpp

    Copyright (c) 2004 by Olivier Goffart        <ogoffart @ kde.org>

    *************************************************************************
    *                                                                       *
    * 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.                                   *
    *                                                                       *
    *************************************************************************
*/
#include "cryptographyguiclient.h"
#include "cryptographyplugin.h"

#include "kopetemetacontact.h"
#include "kopetecontact.h"
#include "kopetechatsession.h"
#include "kopeteview.h"

#include <kaction.h>
#include <ktoggleaction.h>
#include <kconfig.h>
#include <klocale.h>
#include <kgenericfactory.h>
#include <kicon.h>
#include <kmessagebox.h>

#include <QList>

class CryptographyPlugin;

CryptographyGUIClient::CryptographyGUIClient(Kopete::ChatSession *parent )
 : QObject(parent) , KXMLGUIClient(parent)
{
	if(!parent || parent->members().isEmpty())
	{
		deleteLater(); //we refuse to build this client, it is based on wrong parametters
		return;
	}

	QList<Kopete::Contact*> mb=parent->members();
	Kopete::MetaContact *first=mb.first()->metaContact();

	bool wantCrypto=true, keysAvailable=true;

	foreach( Kopete::Contact *c , parent->members() )
	{
		Kopete::MetaContact *mc=c->metaContact();
		if(!mc)
		{
			deleteLater();
			return;
		}
		if( mc->pluginData( CryptographyPlugin::plugin(), "encrypt_messages"  ) == "off" )
			wantCrypto = false;
		if( mc->pluginData( CryptographyPlugin::plugin(), "gpgKey" ).isEmpty() )
			keysAvailable = false;
	}

	setInstance( KGenericFactory<CryptographyPlugin>::instance() );

	m_action=new KToggleAction( KIcon("encrypted"), i18n("Encrypt Messages" ), actionCollection() , "cryptographyToggle" );
	m_action->setChecked(wantCrypto && keysAvailable);
	connect( m_action, SIGNAL(triggered(bool)), this, SLOT(slotToggled()) );

	setXMLFile("cryptographychatui.rc");
}

CryptographyGUIClient::~CryptographyGUIClient()
{}

void CryptographyGUIClient::slotToggled()
{
	Kopete::ChatSession *csn = static_cast<Kopete::ChatSession *>( parent() );
	QStringList keyless;

	Kopete::MetaContact *first=0L;
	foreach( Kopete::Contact * c , csn->members() )
	{
		Kopete::MetaContact *mc = c->metaContact();
		if(!mc)
			continue;

		if(!first)
			first=mc;

		if( mc->pluginData( CryptographyPlugin::plugin(), "gpgKey" ).isEmpty() )
			keyless.append(mc->displayName());
	}

	if( m_action->isChecked() && !keyless.isEmpty() )
	{
		QWidget *w = 0;
		if ( csn->view() )
			w = csn->view()->mainWidget();

		KMessageBox::sorry( w,
							i18np("To send encrypted messages to %1, you still need to select a public key for this contact.", "To send encrypted messages to them, you still need to select a public key for each of these contacts:\n%1", keyless.count() , keyless.join( "\n" ) ),
							i18np( "Missing public key", "Missing public keys", keyless.count() ) );

		m_action->setChecked( false );
	}

	first->setPluginData( CryptographyPlugin::plugin() , "encrypt_messages" ,
						  m_action->isChecked() ? "on" : "off" );
}

#include "cryptographyguiclient.moc"

<|endoftext|>


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

#include "sfx/sfxProvider.h"
#include "sfx/fmod/sfxFMODDevice.h"
#include "core/util/safeRelease.h"
#include "console/console.h"
#include "core/util/safeDelete.h"
#include "core/module.h"
#include "console/consoleTypes.h"

class SFXFMODProvider : public SFXProvider
{
public:

   SFXFMODProvider()
      : SFXProvider( "FMOD" )
   {
      Con::addVariable( "$SFX::Device::fmodNumEventSources", TypeS32, &SFXFMODDevice::smStatNumEventSources,
         "The current number of SFXFMODEventSource instances in the system.\n"
         "This tells the number of sounds in the system that are currently playing FMOD Designer events.\n\n"
         "@note Only relevant if an %FMOD sound device is used.\n\n"
         "@ingroup SFXFMOD" );
      Con::addVariable( "$SFX::Device::fmodCoreMem", TypeS32, &SFXFMODDevice::smStatMemUsageCore,
         "Current number of bytes allocated by the core %FMOD sound system.\n\n"
         "@note Only relevant if an %FMOD sound device is used.\n\n"
         "@ingroup SFXFMOD" );
      Con::addVariable( "$SFX::Device::fmodEventMem", TypeS32, &SFXFMODDevice::smStatMemUsageEvents,
         "Current number of bytes allocated by the %FMOD Designer event system.\n\n"
         "@note Only relevant if an %FMOD sound device is used and the FMOD event DLL is loaded.\n\n"
         "@ingroup SFXFMOD" );

      Con::addVariable( "$pref::SFX::FMOD::disableSoftware", TypeBool, &SFXFMODDevice::smPrefDisableSoftware,
         "Whether to disable the %FMOD software mixer to conserve memory.\n"
         "All sounds not created with SFXDescription::useHardware or using DSP effects will fail to load.\n\n"
         "@note Only applies when using an %FMOD sound device.\n\n"
         "@ingroup SFXFMOD" );
      Con::addVariable( "$pref::SFX::FMOD::useSoftwareHRTF", TypeBool, &SFXFMODDevice::smPrefUseSoftwareHRTF,
         "Whether to enable HRTF in %FMOD's software mixer.\n"
         "This will add a lowpass filter effect to the DSP effect chain of all sounds mixed in software.\n\n"
         "@note Only applies when using an %FMOD sound device.\n\n"
         "@ingroup SFXFMOD" );
      Con::addVariable( "$pref::SFX::FMOD::enableProfile", TypeBool, &SFXFMODDevice::smPrefEnableProfile,
         "Whether to enable support for %FMOD's profiler.\n\n"
         "@note Only applies when using an %FMOD sound device.\n\n"
         "@ref FMOD_profiler\n\n"
         "@ingroup SFXFMOD" );
      Con::addVariable( "$pref::SFX::FMOD::DSoundHRTF", TypeString, &SFXFMODDevice::smPrefDSoundHRTF,
         "The type of HRTF to use for hardware-mixed 3D sounds when %FMOD is using DirectSound for sound output "
         "and hardware-acceleration is not available.\n\n"
         "Options are\n"
         "- \"none\": simple stereo panning/doppler/attenuation\n"
         "- \"light\": slightly higher quality than \"none\"\n"
         "- \"full\": full quality 3D playback\n\n"
         "@note Only applies when using an %FMOD sound device.\n\n"
         "@ingroup SFXFMOD" );
      Con::addVariable( "$pref::SFX::FMOD::pluginPath", TypeString, &SFXFMODDevice::smPrefPluginPath,
         "%Path to additional %FMOD plugins.\n\n"
         "@note Only applies when using an %FMOD sound device.\n\n"
         "@ingroup SFXFMOD" );
   }
   virtual ~SFXFMODProvider();

protected:
   FModFNTable mFMod;

   struct FModDeviceInfo : SFXDeviceInfo
   {
      FMOD_CAPS mCaps;
      FMOD_SPEAKERMODE mSpeakerMode;
   };

   void init();

   bool _createSystem();

public:

   SFXDevice* createDevice( const String& deviceName, bool useHardware, S32 maxBuffers );

};

MODULE_BEGIN( FMOD )

   MODULE_INIT_BEFORE( SFX )
   MODULE_SHUTDOWN_AFTER( SFX )

   SFXFMODProvider* mProvider;

   MODULE_INIT
   {
      mProvider = new SFXFMODProvider;
   }

   MODULE_SHUTDOWN
   {
      delete mProvider;
   }

MODULE_END;

//------------------------------------------------------------------------------
// Helper

bool fmodBindFunction( DLibrary *dll, void *&fnAddress, const char* name )
{
   if( !dll )
      return false;

   fnAddress = dll->bind( name );

   if (!fnAddress)
      Con::warnf( "FMOD Loader: DLL bind failed for %s", name );

   return fnAddress != 0;
}

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

void SFXFMODProvider::init()
{
#ifdef TORQUE_FMOD_STATIC

   // FMOD statically linked.

   mFMod.isLoaded = true;
   #define FMOD_FUNCTION(fn_name, fn_args) \
      (*(void**)&mFMod.fn_name.fn) = &fn_name;

   #ifndef TORQUE_FMOD_NO_EVENTS
   mFMod.eventIsLoaded = true;
      #define FMOD_EVENT_FUNCTION(fn_name, fn_args) \
         (*(void**)&mFMod.fn_name.fn) = &fn_name;
   #else
      #define FMOD_EVENT_FUNCTION( fn_name, fn_args )
   #endif

   #include FMOD_FN_FILE

   #undef FMOD_FUNCTION
   #undef FMOD_EVENT_FUNCTION

#else

   // FMOD dynamically linked.

   const char* dllName;
   const char* pDllName; // plugin-based DLL
   const char* eventDllName;

#ifdef TORQUE_OS_WIN
   dllName = "fmodex.dll";
   pDllName = "fmodexp.dll";
   eventDllName = "fmod_event.dll";
#elif defined( TORQUE_OS_MAC )
   dllName = "libfmodex.dylib";
   pDllName = "libfmodexp.dylib";
   eventDllName = "libfmodevent.dylib";
#else
#  warning Need to set FMOD DLL filename for platform.
   return;
#endif

   // Grab the functions we'll want from the fmod DLL.
   mFMod.dllRef = OsLoadLibrary( dllName );

   // Try the plugin-based version.
   if( !mFMod.dllRef )
      mFMod.dllRef = OsLoadLibrary( pDllName );

   if(!mFMod.dllRef)
   {
      Con::warnf( "SFXFMODProvider - Could not locate '%s' or '%s' - FMOD  not available.", dllName, pDllName );
      return;
   }

   mFMod.eventDllRef = OsLoadLibrary( eventDllName );
   if(!mFMod.eventDllRef)
      Con::warnf( "SFXFMODProvider - Could not locate %s - FMOD Designer integration not available.", eventDllName );

   mFMod.isLoaded = true;
   mFMod.eventIsLoaded = true;

   #define FMOD_FUNCTION(fn_name, fn_args) \
      mFMod.isLoaded &= fmodBindFunction(mFMod.dllRef, *(void**)&mFMod.fn_name.fn, #fn_name);
   #define FMOD_EVENT_FUNCTION(fn_name, fn_args) \
      mFMod.eventIsLoaded &= fmodBindFunction(mFMod.eventDllRef, *(void**)&mFMod.fn_name.fn, #fn_name);

   #include FMOD_FN_FILE

   #undef FMOD_FUNCTION
   #undef FMOD_EVENT_FUNCTION

   if(mFMod.isLoaded == false)
   {
      Con::warnf("SFXFMODProvider - Could not load %s - FMOD not available.", dllName);
      return;
   }
   if( !mFMod.eventIsLoaded && mFMod.eventDllRef )
      Con::warnf("SFXFMODProvider - Could not load %s - FMOD Designer integration not available.", eventDllName);

#endif

   FMOD_RESULT res;

   // Create the FMOD system object.

   if( !_createSystem() )
      return;

   // Check that the Ex API version is OK.

   unsigned int version;
   res = mFMod.FMOD_System_GetVersion(SFXFMODDevice::smSystem, &version);
   FModAssert(res, "SFXFMODProvider - Failed to get FMOD version!");

   Con::printf( "SFXFMODProvider - FMOD Ex API version: %x.%x.%x",
      ( version & 0xffff0000 ) >> 16,
      ( version & 0x0000ff00 ) >> 8,
      ( version & 0x000000ff )
   );

   if(version < FMOD_VERSION)
   {
      Con::warnf("SFXFMODProvider - FMOD Ex API version in DLL is too old - FMOD  not available.");
      return;
   }

   // Check that the Designer API version is ok.

   if( mFMod.eventIsLoaded )
   {
      res = mFMod.FMOD_EventSystem_GetVersion( SFXFMODDevice::smEventSystem, &version );
      FModAssert(res, "SFXFMODProvider - Failed to get FMOD version!");

      Con::printf( "SFXFMODProvider - FMOD Designer API version: %x.%x.%x",
         ( version & 0xffff0000 ) >> 16,
         ( version & 0x0000ff00 ) >> 8,
         ( version & 0x000000ff )
      );

      if( version < FMOD_EVENT_VERSION )
      {
         Con::errorf( "SFXFMODProvider - FMOD Designer API version in DLL is too old!" );
         return;
      }
   }

   // Now, enumerate our devices.
   int numDrivers;
   res = mFMod.FMOD_System_GetNumDrivers(SFXFMODDevice::smSystem, &numDrivers);
   FModAssert(res, "SFXFMODProvider - Failed to get driver count - FMOD  not available.");

   char nameBuff[256];

   for(S32 i=0; i<numDrivers; i++)
   {
      res = mFMod.FMOD_System_GetDriverInfo(SFXFMODDevice::smSystem, i, nameBuff, 256, ( FMOD_GUID* ) NULL);
      if( res != FMOD_OK )
      {
         Con::errorf( "SFXFMODProvider - Failed to get driver name (%s)", FMODResultToString( res ).c_str() );
         continue;
      }
      nameBuff[ 255 ] = '\0';

      FMOD_CAPS caps;
      FMOD_SPEAKERMODE speakerMode;
      res = mFMod.FMOD_System_GetDriverCaps( SFXFMODDevice::smSystem, i, &caps, ( int* ) 0, &speakerMode );
      if( res != FMOD_OK )
      {
         Con::errorf( "SFXFMODProvider - Failed to get driver caps (%s)", FMODResultToString( res ).c_str() );
         continue;
      }

      // Great - got something - so add it to the list of options.
      FModDeviceInfo *fmodInfo = new FModDeviceInfo();
      fmodInfo->name = String( nameBuff );
      fmodInfo->hasHardware = caps & FMOD_CAPS_HARDWARE;
      fmodInfo->maxBuffers = 32;
      fmodInfo->driver = String();
      fmodInfo->mCaps = caps;
      fmodInfo->mSpeakerMode = speakerMode;

      mDeviceInfo.push_back(fmodInfo);
   }

   // Did we get any devices?
   if ( mDeviceInfo.empty() )
   {
      Con::warnf( "SFXFMODProvider - No valid devices found - FMOD  not available." );
      return;
   }

   // TODO: FMOD_Memory_Initialize
#ifdef TORQUE_OS_XENON
   const dsize_t memSz = 5 * 1024 * 1024;
   void *memBuffer = XPhysicalAlloc( memSz, MAXULONG_PTR, 0, PAGE_READWRITE );
   mFMod.FMOD_Memory_Initialize( memBuffer, memSz, FMOD_MEMORY_ALLOCCALLBACK(NULL), FMOD_MEMORY_REALLOCCALLBACK(NULL), FMOD_MEMORY_FREECALLBACK(NULL) );
#endif

   // Wow, we made it - register the provider.
   regProvider( this );
}

SFXFMODProvider::~SFXFMODProvider()
{
   if( SFXFMODDevice::smEventSystem )
   {
      mFMod.FMOD_EventSystem_Release( SFXFMODDevice::smEventSystem );
      SFXFMODDevice::smEventSystem = NULL;
      SFXFMODDevice::smSystem = NULL;
   }
   else if( SFXFMODDevice::smSystem )
   {
      mFMod.FMOD_System_Release( SFXFMODDevice::smSystem );
      SFXFMODDevice::smSystem = NULL;
   }
}

SFXDevice* SFXFMODProvider::createDevice( const String& deviceName, bool useHardware, S32 maxBuffers )
{
   FModDeviceInfo* info = dynamic_cast< FModDeviceInfo* >
      ( _findDeviceInfo( deviceName ) );

   if( !info )
      return NULL;

   if( !SFXFMODDevice::smSystem && !_createSystem() )
      return false;

   SFXFMODDevice* device = new SFXFMODDevice(this, &mFMod, 0, info->name );
   if( !device->_init() )
      SAFE_DELETE( device );

   return device;
}

bool SFXFMODProvider::_createSystem()
{
   AssertFatal( !SFXFMODDevice::smEventSystem, "SFXFMODProvider::_createSystem() - event system already created!" );
   AssertFatal( !SFXFMODDevice::smSystem, "SFXFMODProvider::_createSystem() - system already created!" );

   if( mFMod.eventIsLoaded )
   {
      FMOD_RESULT res = mFMod.FMOD_EventSystem_Create( &SFXFMODDevice::smEventSystem );
      if( res != FMOD_OK )
      {
         Con::errorf( "SFXFMODProvider - could not create the FMOD event system." );
         return false;
      }

      res = mFMod.FMOD_EventSystem_GetSystemObject( SFXFMODDevice::smEventSystem, &SFXFMODDevice::smSystem );
      if( res != FMOD_OK )
      {
         Con::errorf( "SFXFMODProvider - could not retrieve the FMOD system object." );
         return false;
      }
   }
   else
   {
      // Allocate the FMod system.

      FMOD_RESULT res = mFMod.FMOD_System_Create( &SFXFMODDevice::smSystem );
      if( res != FMOD_OK )
      {
         // Failed - deal with it!
         Con::errorf("SFXFMODProvider - could not create the FMOD system.");
         return false;
      }
   }

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

#include "sfx/sfxProvider.h"
#include "sfx/fmod/sfxFMODDevice.h"
#include "core/util/safeRelease.h"
#include "console/console.h"
#include "core/util/safeDelete.h"
#include "core/module.h"
#include "console/consoleTypes.h"

class SFXFMODProvider : public SFXProvider
{
public:

   SFXFMODProvider()
      : SFXProvider( "FMOD" )
   {
      Con::addVariable( "$SFX::Device::fmodNumEventSources", TypeS32, &SFXFMODDevice::smStatNumEventSources,
         "The current number of SFXFMODEventSource instances in the system.\n"
         "This tells the number of sounds in the system that are currently playing FMOD Designer events.\n\n"
         "@note Only relevant if an %FMOD sound device is used.\n\n"
         "@ingroup SFXFMOD" );
      Con::addVariable( "$SFX::Device::fmodCoreMem", TypeS32, &SFXFMODDevice::smStatMemUsageCore,
         "Current number of bytes allocated by the core %FMOD sound system.\n\n"
         "@note Only relevant if an %FMOD sound device is used.\n\n"
         "@ingroup SFXFMOD" );
      Con::addVariable( "$SFX::Device::fmodEventMem", TypeS32, &SFXFMODDevice::smStatMemUsageEvents,
         "Current number of bytes allocated by the %FMOD Designer event system.\n\n"
         "@note Only relevant if an %FMOD sound device is used and the FMOD event DLL is loaded.\n\n"
         "@ingroup SFXFMOD" );

      Con::addVariable( "$pref::SFX::FMOD::disableSoftware", TypeBool, &SFXFMODDevice::smPrefDisableSoftware,
         "Whether to disable the %FMOD software mixer to conserve memory.\n"
         "All sounds not created with SFXDescription::useHardware or using DSP effects will fail to load.\n\n"
         "@note Only applies when using an %FMOD sound device.\n\n"
         "@ingroup SFXFMOD" );
      Con::addVariable( "$pref::SFX::FMOD::useSoftwareHRTF", TypeBool, &SFXFMODDevice::smPrefUseSoftwareHRTF,
         "Whether to enable HRTF in %FMOD's software mixer.\n"
         "This will add a lowpass filter effect to the DSP effect chain of all sounds mixed in software.\n\n"
         "@note Only applies when using an %FMOD sound device.\n\n"
         "@ingroup SFXFMOD" );
      Con::addVariable( "$pref::SFX::FMOD::enableProfile", TypeBool, &SFXFMODDevice::smPrefEnableProfile,
         "Whether to enable support for %FMOD's profiler.\n\n"
         "@note Only applies when using an %FMOD sound device.\n\n"
         "@ref FMOD_profiler\n\n"
         "@ingroup SFXFMOD" );
      Con::addVariable( "$pref::SFX::FMOD::DSoundHRTF", TypeString, &SFXFMODDevice::smPrefDSoundHRTF,
         "The type of HRTF to use for hardware-mixed 3D sounds when %FMOD is using DirectSound for sound output "
         "and hardware-acceleration is not available.\n\n"
         "Options are\n"
         "- \"none\": simple stereo panning/doppler/attenuation\n"
         "- \"light\": slightly higher quality than \"none\"\n"
         "- \"full\": full quality 3D playback\n\n"
         "@note Only applies when using an %FMOD sound device.\n\n"
         "@ingroup SFXFMOD" );
      Con::addVariable( "$pref::SFX::FMOD::pluginPath", TypeString, &SFXFMODDevice::smPrefPluginPath,
         "%Path to additional %FMOD plugins.\n\n"
         "@note Only applies when using an %FMOD sound device.\n\n"
         "@ingroup SFXFMOD" );
   }
   virtual ~SFXFMODProvider();

protected:
   FModFNTable mFMod;

   struct FModDeviceInfo : SFXDeviceInfo
   {
      FMOD_CAPS mCaps;
      FMOD_SPEAKERMODE mSpeakerMode;
   };

   void init();

   bool _createSystem();

public:

   SFXDevice* createDevice( const String& deviceName, bool useHardware, S32 maxBuffers );

};

MODULE_BEGIN( FMOD )

   MODULE_INIT_BEFORE( SFX )
   MODULE_SHUTDOWN_AFTER( SFX )

   SFXFMODProvider* mProvider;

   MODULE_INIT
   {
      mProvider = new SFXFMODProvider;
   }

   MODULE_SHUTDOWN
   {
      delete mProvider;
   }

MODULE_END;

//------------------------------------------------------------------------------
// Helper

bool fmodBindFunction( DLibrary *dll, void *&fnAddress, const char* name )
{
   if( !dll )
      return false;

   fnAddress = dll->bind( name );

   if (!fnAddress)
      Con::warnf( "FMOD Loader: DLL bind failed for %s", name );

   return fnAddress != 0;
}

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

void SFXFMODProvider::init()
{
#ifdef TORQUE_FMOD_STATIC

   // FMOD statically linked.

   mFMod.isLoaded = true;
   #define FMOD_FUNCTION(fn_name, fn_args) \
      (*(void**)&mFMod.fn_name.fn) = &fn_name;

   #ifndef TORQUE_FMOD_NO_EVENTS
   mFMod.eventIsLoaded = true;
      #define FMOD_EVENT_FUNCTION(fn_name, fn_args) \
         (*(void**)&mFMod.fn_name.fn) = &fn_name;
   #else
      #define FMOD_EVENT_FUNCTION( fn_name, fn_args )
   #endif

   #include FMOD_FN_FILE

   #undef FMOD_FUNCTION
   #undef FMOD_EVENT_FUNCTION

#else

   // FMOD dynamically linked.

   const char* dllName;
   const char* pDllName; // plugin-based DLL
   const char* eventDllName;

#ifdef _WIN64
   dllName = "fmodex64.dll";
   pDllName = "fmodexp64.dll";
   eventDllName = "fmod_event64.dll";
#elif defined(TORQUE_OS_WIN32)
   dllName = "fmodex.dll";
   pDllName = "fmodexp.dll";
   eventDllName = "fmod_event.dll";
#elif defined( TORQUE_OS_MAC )
   dllName = "libfmodex.dylib";
   pDllName = "libfmodexp.dylib";
   eventDllName = "libfmodevent.dylib";
#else
#  warning Need to set FMOD DLL filename for platform.
   return;
#endif

   // Grab the functions we'll want from the fmod DLL.
   mFMod.dllRef = OsLoadLibrary( dllName );

   // Try the plugin-based version.
   if( !mFMod.dllRef )
      mFMod.dllRef = OsLoadLibrary( pDllName );

   if(!mFMod.dllRef)
   {
      Con::warnf( "SFXFMODProvider - Could not locate '%s' or '%s' - FMOD  not available.", dllName, pDllName );
      return;
   }

   mFMod.eventDllRef = OsLoadLibrary( eventDllName );
   if(!mFMod.eventDllRef)
      Con::warnf( "SFXFMODProvider - Could not locate %s - FMOD Designer integration not available.", eventDllName );

   mFMod.isLoaded = true;
   mFMod.eventIsLoaded = true;

   #define FMOD_FUNCTION(fn_name, fn_args) \
      mFMod.isLoaded &= fmodBindFunction(mFMod.dllRef, *(void**)&mFMod.fn_name.fn, #fn_name);
   #define FMOD_EVENT_FUNCTION(fn_name, fn_args) \
      mFMod.eventIsLoaded &= fmodBindFunction(mFMod.eventDllRef, *(void**)&mFMod.fn_name.fn, #fn_name);

   #include FMOD_FN_FILE

   #undef FMOD_FUNCTION
   #undef FMOD_EVENT_FUNCTION

   if(mFMod.isLoaded == false)
   {
      Con::warnf("SFXFMODProvider - Could not load %s - FMOD not available.", dllName);
      return;
   }
   if( !mFMod.eventIsLoaded && mFMod.eventDllRef )
      Con::warnf("SFXFMODProvider - Could not load %s - FMOD Designer integration not available.", eventDllName);

#endif

   FMOD_RESULT res;

   // Create the FMOD system object.

   if( !_createSystem() )
      return;

   // Check that the Ex API version is OK.

   unsigned int version;
   res = mFMod.FMOD_System_GetVersion(SFXFMODDevice::smSystem, &version);
   FModAssert(res, "SFXFMODProvider - Failed to get FMOD version!");

   Con::printf( "SFXFMODProvider - FMOD Ex API version: %x.%x.%x",
      ( version & 0xffff0000 ) >> 16,
      ( version & 0x0000ff00 ) >> 8,
      ( version & 0x000000ff )
   );

   if(version < FMOD_VERSION)
   {
      Con::warnf("SFXFMODProvider - FMOD Ex API version in DLL is too old - FMOD  not available.");
      return;
   }

   // Check that the Designer API version is ok.

   if( mFMod.eventIsLoaded )
   {
      res = mFMod.FMOD_EventSystem_GetVersion( SFXFMODDevice::smEventSystem, &version );
      FModAssert(res, "SFXFMODProvider - Failed to get FMOD version!");

      Con::printf( "SFXFMODProvider - FMOD Designer API version: %x.%x.%x",
         ( version & 0xffff0000 ) >> 16,
         ( version & 0x0000ff00 ) >> 8,
         ( version & 0x000000ff )
      );

      if( version < FMOD_EVENT_VERSION )
      {
         Con::errorf( "SFXFMODProvider - FMOD Designer API version in DLL is too old!" );
         return;
      }
   }

   // Now, enumerate our devices.
   int numDrivers;
   res = mFMod.FMOD_System_GetNumDrivers(SFXFMODDevice::smSystem, &numDrivers);
   FModAssert(res, "SFXFMODProvider - Failed to get driver count - FMOD  not available.");

   char nameBuff[256];

   for(S32 i=0; i<numDrivers; i++)
   {
      res = mFMod.FMOD_System_GetDriverInfo(SFXFMODDevice::smSystem, i, nameBuff, 256, ( FMOD_GUID* ) NULL);
      if( res != FMOD_OK )
      {
         Con::errorf( "SFXFMODProvider - Failed to get driver name (%s)", FMODResultToString( res ).c_str() );
         continue;
      }
      nameBuff[ 255 ] = '\0';

      FMOD_CAPS caps;
      FMOD_SPEAKERMODE speakerMode;
      res = mFMod.FMOD_System_GetDriverCaps( SFXFMODDevice::smSystem, i, &caps, ( int* ) 0, &speakerMode );
      if( res != FMOD_OK )
      {
         Con::errorf( "SFXFMODProvider - Failed to get driver caps (%s)", FMODResultToString( res ).c_str() );
         continue;
      }

      // Great - got something - so add it to the list of options.
      FModDeviceInfo *fmodInfo = new FModDeviceInfo();
      fmodInfo->name = String( nameBuff );
      fmodInfo->hasHardware = caps & FMOD_CAPS_HARDWARE;
      fmodInfo->maxBuffers = 32;
      fmodInfo->driver = String();
      fmodInfo->mCaps = caps;
      fmodInfo->mSpeakerMode = speakerMode;

      mDeviceInfo.push_back(fmodInfo);
   }

   // Did we get any devices?
   if ( mDeviceInfo.empty() )
   {
      Con::warnf( "SFXFMODProvider - No valid devices found - FMOD  not available." );
      return;
   }

   // TODO: FMOD_Memory_Initialize
#ifdef TORQUE_OS_XENON
   const dsize_t memSz = 5 * 1024 * 1024;
   void *memBuffer = XPhysicalAlloc( memSz, MAXULONG_PTR, 0, PAGE_READWRITE );
   mFMod.FMOD_Memory_Initialize( memBuffer, memSz, FMOD_MEMORY_ALLOCCALLBACK(NULL), FMOD_MEMORY_REALLOCCALLBACK(NULL), FMOD_MEMORY_FREECALLBACK(NULL) );
#endif

   // Wow, we made it - register the provider.
   regProvider( this );
}

SFXFMODProvider::~SFXFMODProvider()
{
   if( SFXFMODDevice::smEventSystem )
   {
      mFMod.FMOD_EventSystem_Release( SFXFMODDevice::smEventSystem );
      SFXFMODDevice::smEventSystem = NULL;
      SFXFMODDevice::smSystem = NULL;
   }
   else if( SFXFMODDevice::smSystem )
   {
      mFMod.FMOD_System_Release( SFXFMODDevice::smSystem );
      SFXFMODDevice::smSystem = NULL;
   }
}

SFXDevice* SFXFMODProvider::createDevice( const String& deviceName, bool useHardware, S32 maxBuffers )
{
   FModDeviceInfo* info = dynamic_cast< FModDeviceInfo* >
      ( _findDeviceInfo( deviceName ) );

   if( !info )
      return NULL;

   if( !SFXFMODDevice::smSystem && !_createSystem() )
      return false;

   SFXFMODDevice* device = new SFXFMODDevice(this, &mFMod, 0, info->name );
   if( !device->_init() )
      SAFE_DELETE( device );

   return device;
}

bool SFXFMODProvider::_createSystem()
{
   AssertFatal( !SFXFMODDevice::smEventSystem, "SFXFMODProvider::_createSystem() - event system already created!" );
   AssertFatal( !SFXFMODDevice::smSystem, "SFXFMODProvider::_createSystem() - system already created!" );

   if( mFMod.eventIsLoaded )
   {
      FMOD_RESULT res = mFMod.FMOD_EventSystem_Create( &SFXFMODDevice::smEventSystem );
      if( res != FMOD_OK )
      {
         Con::errorf( "SFXFMODProvider - could not create the FMOD event system." );
         return false;
      }

      res = mFMod.FMOD_EventSystem_GetSystemObject( SFXFMODDevice::smEventSystem, &SFXFMODDevice::smSystem );
      if( res != FMOD_OK )
      {
         Con::errorf( "SFXFMODProvider - could not retrieve the FMOD system object." );
         return false;
      }
   }
   else
   {
      // Allocate the FMod system.

      FMOD_RESULT res = mFMod.FMOD_System_Create( &SFXFMODDevice::smSystem );
      if( res != FMOD_OK )
      {
         // Failed - deal with it!
         Con::errorf("SFXFMODProvider - could not create the FMOD system.");
         return false;
      }
   }

   return true;
}
<|endoftext|>


<commit_before>/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.

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 "tensorflow_lite_support/c/task/vision/image_segmenter.h"

#include <memory>

#include "tensorflow_lite_support/c/common_utils.h"
#include "tensorflow_lite_support/c/task/core/utils/base_options_utils.h"
#include "tensorflow_lite_support/c/task/vision/utils/frame_buffer_cpp_c_utils.h"
#include "tensorflow_lite_support/cc/task/vision/image_segmenter.h"
#include "tensorflow_lite_support/cc/task/vision/proto/image_segmenter_options_proto_inc.h"
#include "tensorflow_lite_support/cc/task/vision/proto/segmentations_proto_inc.h"

namespace {
using ::tflite::support::StatusOr;
using SegmentationResultCpp = ::tflite::task::vision::SegmentationResult;
using SegmentationCpp = ::tflite::task::vision::Segmentation;
using ColoredLabelCpp = ::tflite::task::vision::Segmentation_ColoredLabel;
using ImageSegmenterCpp = ::tflite::task::vision::ImageSegmenter;
using ImageSegmenterOptionsCpp = ::tflite::task::vision::ImageSegmenterOptions;
using FrameBufferCpp = ::tflite::task::vision::FrameBuffer;
using OutputTypeCpp = ::tflite::task::vision::ImageSegmenterOptions_OutputType;
using ::tflite::support::TfLiteSupportStatus;

StatusOr<ImageSegmenterOptionsCpp> CreateImageSegmenterCppOptionsFromCOptions(
    const TfLiteImageSegmenterOptions* c_options) {
  if (c_options == nullptr) {
    return CreateStatusWithPayload(
        absl::StatusCode::kInvalidArgument,
        absl::StrFormat("Expected non null options."),
        TfLiteSupportStatus::kInvalidArgumentError);
  }

  ImageSegmenterOptionsCpp cpp_options = {};

  // More file sources can be added in else ifs
  if (c_options->base_options.model_file.file_path)
    cpp_options.mutable_base_options()->mutable_model_file()->set_file_name(
        c_options->base_options.model_file.file_path);

  // c_options->base_options.compute_settings.num_threads is expected to be
  // set to value > 0 or -1. Otherwise invoking
  // ImageSegmenterCpp::CreateFromOptions() results in a not ok status.
  cpp_options.mutable_base_options()
      ->mutable_compute_settings()
      ->mutable_tflite_settings()
      ->mutable_cpu_settings()
      ->set_num_threads(
          c_options->base_options.compute_settings.cpu_settings.num_threads);

  cpp_options.set_output_type((OutputTypeCpp)c_options->output_type);

  // Check needed since setting a nullptr for this field results in a segfault
  // on invocation of ImageSegmenterCpp::CreateFromOptions().
  if (c_options->display_names_locale) {
    cpp_options.set_display_names_locale(c_options->display_names_locale);
  }

  return cpp_options;
}
}  // namespace

#ifdef __cplusplus
extern "C" {
#endif  // __cplusplus

struct TfLiteImageSegmenter {
  std::unique_ptr<ImageSegmenterCpp> impl;
};

TfLiteImageSegmenterOptions TfLiteImageSegmenterOptionsCreate() {
  // Use brace-enclosed initializer list will break the Kokoro test.
  TfLiteImageSegmenterOptions options;
  options.base_options = tflite::task::core::CreateDefaultBaseOptions();
  options.display_names_locale = nullptr;
  options.output_type = kCategoryMask;

  return options;
}

TfLiteImageSegmenter* TfLiteImageSegmenterFromOptions(
    const TfLiteImageSegmenterOptions* options, TfLiteSupportError** error) {
  StatusOr<ImageSegmenterOptionsCpp> cpp_option_status =
      CreateImageSegmenterCppOptionsFromCOptions(options);

  if (!cpp_option_status.ok()) {
    ::tflite::support::CreateTfLiteSupportErrorWithStatus(
        cpp_option_status.status(), error);
    return nullptr;
  }
  StatusOr<std::unique_ptr<ImageSegmenterCpp>> segmenter_status =
      ImageSegmenterCpp::CreateFromOptions(cpp_option_status.value());

  if (segmenter_status.ok()) {
    return new TfLiteImageSegmenter{.impl =
                                        std::move(segmenter_status.value())};
  } else {
    ::tflite::support::CreateTfLiteSupportErrorWithStatus(
        segmenter_status.status(), error);
    return nullptr;
  }
}

TfLiteSegmentationResult* GetSegmentationResultCStruct(
    const SegmentationResultCpp& segmentation_result_cpp) {
  auto c_segmentations =
      new TfLiteSegmentation[segmentation_result_cpp.segmentation_size()]();

  for (int i = 0; i < segmentation_result_cpp.segmentation_size(); ++i) {
    const SegmentationCpp& segmentation =
        segmentation_result_cpp.segmentation(i);

    c_segmentations[i].width = segmentation.width();
    c_segmentations[i].height = segmentation.height();
    c_segmentations[i].colored_labels_size = segmentation.colored_labels_size();

    auto c_colored_labels =
        new TfLiteColoredLabel[segmentation.colored_labels_size()]();

    if (segmentation.has_category_mask()) {
      c_segmentations[i].category_mask =
          new uint8_t[segmentation.width() * segmentation.height()];

      std::memcpy(
          c_segmentations[i].category_mask,
          reinterpret_cast<const uint8_t*>(segmentation.category_mask().data()),
          segmentation.width() * segmentation.height() * sizeof(uint8_t));

    } else if (segmentation.has_confidence_masks()) {
      c_segmentations[i].confidence_masks =
          new float*[segmentation.colored_labels_size()];
      for (int k = 0; k < segmentation.colored_labels_size(); ++k) {
        c_segmentations[i].confidence_masks[k] =
            new float[segmentation.width() * segmentation.height()];

        std::memcpy(
            c_segmentations[i].confidence_masks[k],
            reinterpret_cast<const float*>(segmentation.confidence_masks()
                                               .confidence_mask(k)
                                               .value()
                                               .data()),
            segmentation.width() * segmentation.height() * sizeof(float));
      }
    }

    for (int j = 0; j < segmentation.colored_labels_size(); ++j) {
      const ColoredLabelCpp& colored_label = segmentation.colored_labels(j);
      c_colored_labels[j].r = colored_label.r();
      c_colored_labels[j].g = colored_label.g();
      c_colored_labels[j].b = colored_label.b();

      if (colored_label.has_class_name()) {
        c_colored_labels[j].label = strdup(colored_label.class_name().c_str());
      }

      if (colored_label.has_display_name()) {
        c_colored_labels[j].display_name =
            strdup(colored_label.display_name().c_str());
      }
    }
    c_segmentations[i].colored_labels = c_colored_labels;
  }

  auto c_segmentation_result = new TfLiteSegmentationResult;
  c_segmentation_result->segmentations = c_segmentations;
  c_segmentation_result->size = segmentation_result_cpp.segmentation_size();

  return c_segmentation_result;
}

TfLiteSegmentationResult* TfLiteImageSegmenterSegment(
    const TfLiteImageSegmenter* segmenter,
    const TfLiteFrameBuffer* frame_buffer, TfLiteSupportError** error) {
  if (segmenter == nullptr) {
    tflite::support::CreateTfLiteSupportError(
        kInvalidArgumentError, "Expected non null image segmenter.", error);
    return nullptr;
  }

  StatusOr<std::unique_ptr<FrameBufferCpp>> cpp_frame_buffer_status =
      ::tflite::task::vision::CreateCppFrameBuffer(frame_buffer);
  if (!cpp_frame_buffer_status.ok()) {
    tflite::support::CreateTfLiteSupportErrorWithStatus(
        cpp_frame_buffer_status.status(), error);
    return nullptr;
  }

  StatusOr<SegmentationResultCpp> cpp_segmentation_result_status =
      segmenter->impl->Segment(*(cpp_frame_buffer_status.value()));

  if (!cpp_segmentation_result_status.ok()) {
    tflite::support::CreateTfLiteSupportErrorWithStatus(
        cpp_segmentation_result_status.status(), error);
    return nullptr;
  }

  return GetSegmentationResultCStruct(cpp_segmentation_result_status.value());
}

void TfLiteImageSegmenterDelete(TfLiteImageSegmenter* segmenter) {
  delete segmenter;
}

#ifdef __cplusplus
}  // extern "C"
#endif  // __cplusplus
<commit_msg>Cast to appropriate type in C from C++ proto<commit_after>/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.

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 "tensorflow_lite_support/c/task/vision/image_segmenter.h"

#include <memory>

#include "tensorflow_lite_support/c/common_utils.h"
#include "tensorflow_lite_support/c/task/core/utils/base_options_utils.h"
#include "tensorflow_lite_support/c/task/vision/utils/frame_buffer_cpp_c_utils.h"
#include "tensorflow_lite_support/cc/task/vision/image_segmenter.h"
#include "tensorflow_lite_support/cc/task/vision/proto/image_segmenter_options_proto_inc.h"
#include "tensorflow_lite_support/cc/task/vision/proto/segmentations_proto_inc.h"

namespace {
using ::tflite::support::StatusOr;
using SegmentationResultCpp = ::tflite::task::vision::SegmentationResult;
using SegmentationCpp = ::tflite::task::vision::Segmentation;
using ColoredLabelCpp = ::tflite::task::vision::Segmentation_ColoredLabel;
using ImageSegmenterCpp = ::tflite::task::vision::ImageSegmenter;
using ImageSegmenterOptionsCpp = ::tflite::task::vision::ImageSegmenterOptions;
using FrameBufferCpp = ::tflite::task::vision::FrameBuffer;
using OutputTypeCpp = ::tflite::task::vision::ImageSegmenterOptions_OutputType;
using ::tflite::support::TfLiteSupportStatus;

StatusOr<ImageSegmenterOptionsCpp> CreateImageSegmenterCppOptionsFromCOptions(
    const TfLiteImageSegmenterOptions* c_options) {
  if (c_options == nullptr) {
    return CreateStatusWithPayload(
        absl::StatusCode::kInvalidArgument,
        absl::StrFormat("Expected non null options."),
        TfLiteSupportStatus::kInvalidArgumentError);
  }

  ImageSegmenterOptionsCpp cpp_options = {};

  // More file sources can be added in else ifs
  if (c_options->base_options.model_file.file_path)
    cpp_options.mutable_base_options()->mutable_model_file()->set_file_name(
        c_options->base_options.model_file.file_path);

  // c_options->base_options.compute_settings.num_threads is expected to be
  // set to value > 0 or -1. Otherwise invoking
  // ImageSegmenterCpp::CreateFromOptions() results in a not ok status.
  cpp_options.mutable_base_options()
      ->mutable_compute_settings()
      ->mutable_tflite_settings()
      ->mutable_cpu_settings()
      ->set_num_threads(
          c_options->base_options.compute_settings.cpu_settings.num_threads);

  cpp_options.set_output_type((OutputTypeCpp)c_options->output_type);

  // Check needed since setting a nullptr for this field results in a segfault
  // on invocation of ImageSegmenterCpp::CreateFromOptions().
  if (c_options->display_names_locale) {
    cpp_options.set_display_names_locale(c_options->display_names_locale);
  }

  return cpp_options;
}
}  // namespace

#ifdef __cplusplus
extern "C" {
#endif  // __cplusplus

struct TfLiteImageSegmenter {
  std::unique_ptr<ImageSegmenterCpp> impl;
};

TfLiteImageSegmenterOptions TfLiteImageSegmenterOptionsCreate() {
  // Use brace-enclosed initializer list will break the Kokoro test.
  TfLiteImageSegmenterOptions options;
  options.base_options = tflite::task::core::CreateDefaultBaseOptions();
  options.display_names_locale = nullptr;
  options.output_type = kCategoryMask;

  return options;
}

TfLiteImageSegmenter* TfLiteImageSegmenterFromOptions(
    const TfLiteImageSegmenterOptions* options, TfLiteSupportError** error) {
  StatusOr<ImageSegmenterOptionsCpp> cpp_option_status =
      CreateImageSegmenterCppOptionsFromCOptions(options);

  if (!cpp_option_status.ok()) {
    ::tflite::support::CreateTfLiteSupportErrorWithStatus(
        cpp_option_status.status(), error);
    return nullptr;
  }
  StatusOr<std::unique_ptr<ImageSegmenterCpp>> segmenter_status =
      ImageSegmenterCpp::CreateFromOptions(cpp_option_status.value());

  if (segmenter_status.ok()) {
    return new TfLiteImageSegmenter{.impl =
                                        std::move(segmenter_status.value())};
  } else {
    ::tflite::support::CreateTfLiteSupportErrorWithStatus(
        segmenter_status.status(), error);
    return nullptr;
  }
}

TfLiteSegmentationResult* GetSegmentationResultCStruct(
    const SegmentationResultCpp& segmentation_result_cpp) {
  auto c_segmentations =
      new TfLiteSegmentation[segmentation_result_cpp.segmentation_size()]();

  for (int i = 0; i < segmentation_result_cpp.segmentation_size(); ++i) {
    const SegmentationCpp& segmentation =
        segmentation_result_cpp.segmentation(i);

    c_segmentations[i].width = (int)segmentation.width();
    c_segmentations[i].height = (int)segmentation.height();
    c_segmentations[i].colored_labels_size = segmentation.colored_labels_size();

    auto c_colored_labels =
        new TfLiteColoredLabel[segmentation.colored_labels_size()]();

    if (segmentation.has_category_mask()) {
      c_segmentations[i].category_mask =
          new uint8_t[segmentation.width() * segmentation.height()];
      std::memcpy(
          c_segmentations[i].category_mask,
          reinterpret_cast<const uint8_t*>(segmentation.category_mask().data()),
          segmentation.width() * segmentation.height() * sizeof(uint8_t));

    } else if (segmentation.has_confidence_masks()) {
      c_segmentations[i].confidence_masks =
          new float*[segmentation.colored_labels_size()];
      for (int k = 0; k < segmentation.colored_labels_size(); ++k) {
        c_segmentations[i].confidence_masks[k] =
            new float[segmentation.width() * segmentation.height()];

        std::memcpy(
            c_segmentations[i].confidence_masks[k],
            reinterpret_cast<const float*>(segmentation.confidence_masks()
                                               .confidence_mask(k)
                                               .value()
                                               .data()),
            segmentation.width() * segmentation.height() * sizeof(float));
      }
    }

    for (int j = 0; j < segmentation.colored_labels_size(); ++j) {
      const ColoredLabelCpp& colored_label = segmentation.colored_labels(j);
      c_colored_labels[j].r = colored_label.r();
      c_colored_labels[j].g = colored_label.g();
      c_colored_labels[j].b = colored_label.b();

      if (colored_label.has_class_name()) {
        c_colored_labels[j].label = strdup(colored_label.class_name().c_str());
      }

      if (colored_label.has_display_name()) {
        c_colored_labels[j].display_name =
            strdup(colored_label.display_name().c_str());
      }
    }
    c_segmentations[i].colored_labels = c_colored_labels;
  }

  auto c_segmentation_result = new TfLiteSegmentationResult;
  c_segmentation_result->segmentations = c_segmentations;
  c_segmentation_result->size = segmentation_result_cpp.segmentation_size();

  return c_segmentation_result;
}

TfLiteSegmentationResult* TfLiteImageSegmenterSegment(
    const TfLiteImageSegmenter* segmenter,
    const TfLiteFrameBuffer* frame_buffer, TfLiteSupportError** error) {
  if (segmenter == nullptr) {
    tflite::support::CreateTfLiteSupportError(
        kInvalidArgumentError, "Expected non null image segmenter.", error);
    return nullptr;
  }

  StatusOr<std::unique_ptr<FrameBufferCpp>> cpp_frame_buffer_status =
      ::tflite::task::vision::CreateCppFrameBuffer(frame_buffer);
  if (!cpp_frame_buffer_status.ok()) {
    tflite::support::CreateTfLiteSupportErrorWithStatus(
        cpp_frame_buffer_status.status(), error);
    return nullptr;
  }

  StatusOr<SegmentationResultCpp> cpp_segmentation_result_status =
      segmenter->impl->Segment(*(cpp_frame_buffer_status.value()));

  if (!cpp_segmentation_result_status.ok()) {
    tflite::support::CreateTfLiteSupportErrorWithStatus(
        cpp_segmentation_result_status.status(), error);
    return nullptr;
  }

  return GetSegmentationResultCStruct(cpp_segmentation_result_status.value());
}

void TfLiteImageSegmenterDelete(TfLiteImageSegmenter* segmenter) {
  delete segmenter;
}

#ifdef __cplusplus
}  // extern "C"
#endif  // __cplusplus
<|endoftext|>


<commit_before>/**
 *  cppclassinphp.cpp
 *  @author Jasper van Eck<jasper.vaneck@copernica.com>
 *
 *  An example file to show the working of using a C++ class in PHP.
 */

#include "mytestext.h"
/**
 *  Namespace to use
 */
using namespace std;

class MyTestExt : public Php::Base
{

public:
    MyTestExt() {}

    virtual ~MyTestExt() {}

    virtual void __construct() {}

};

// Symbols are exported according to the "C" language
extern "C"
{
    // export the "get_module" function that will be called by the Zend engine
    PHPCPP_EXPORT void *get_module()
    {
        // create extension
        static Php::Extension extension("my_test_ext","0.1a");

        // add the custom class ot the extension
        extension.add(
            "MyTestClass",
            Php::Class<MyTestExt>({

                // Private PHP constructor! You can't instance object of MyTestClass
                Php::Private("__construct", Php::Method<MyTestExt>(&MyTestExt::__construct)),

                Php::Const("version", "v0.01-alpha"),
                Php::Const("PI", 3.14159265),
                Php::Const("IMISNULL"),

                Php::Static("exp", 2.71828182846),
            })
        );

        // return the extension module
        return extension.module();
    }
}
<commit_msg>Removed the static property from the example as this is not currently enabled<commit_after>/**
 *  cppclassinphp.cpp
 *  @author Jasper van Eck<jasper.vaneck@copernica.com>
 *
 *  An example file to show the working of using a C++ class in PHP.
 */

#include "mytestext.h"
/**
 *  Namespace to use
 */
using namespace std;

class MyTestExt : public Php::Base
{

public:
    MyTestExt() {}

    virtual ~MyTestExt() {}

    virtual void __construct() {}

};

// Symbols are exported according to the "C" language
extern "C"
{
    // export the "get_module" function that will be called by the Zend engine
    PHPCPP_EXPORT void *get_module()
    {
        // create extension
        static Php::Extension extension("my_test_ext","0.1a");

        // add the custom class ot the extension
        extension.add(
            "MyTestClass",
            Php::Class<MyTestExt>({

                // Private PHP constructor! You can't instance object of MyTestClass
                Php::Private("__construct", Php::Method<MyTestExt>(&MyTestExt::__construct)),

                Php::Const("version", "v0.01-alpha"),
                Php::Const("PI", 3.14159265),
                Php::Const("IMISNULL"),
            })
        );

        // return the extension module
        return extension.module();
    }
}
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  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.txt
 *
 *  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.
 *
 *=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

//  Software Guide : BeginLatex
//
//  In the same way that custom data can be associated with points in the mesh,
//  it is also possible to associate custom data with cells. The type of the
//  data associated with the cells can be different from the data type
//  associated with points. By default, however, these two types are the same.
//  The following example illustrates how to access data associated with cells.
//  The approach is analogous to the one used to access point data.
//
//  \index{itk::Mesh!Cell data}
//
//  Software Guide : EndLatex

//  Software Guide : BeginLatex
//
//  Consider the example of a mesh containing lines on which values are
//  associated with each line. The mesh and cell header files should be
//  included first.
//
//  Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
#include "itkMesh.h"
#include "itkLineCell.h"
// Software Guide : EndCodeSnippet

int main(int, char *[])
{
  //  Software Guide : BeginLatex
  //
  //  Then the PixelType is defined and the mesh type is instantiated with it.
  //
  //  \index{itk::Mesh!Instantiation}
  //  \index{itk::Mesh!PixelType}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef float                             PixelType;
  typedef itk::Mesh< PixelType, 2 >         MeshType;
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  The \doxygen{LineCell} type can now be instantiated using the traits
  //  taken from the Mesh.
  //
  //  \index{itk::LineCell!Instantiation}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef MeshType::CellType                CellType;
  typedef itk::LineCell< CellType >         LineType;
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  Let's now create a Mesh and insert some points into it. Note that the
  //  dimension of the points matches the dimension of the Mesh. Here we insert
  //  a sequence of points that look like a plot of the $\log()$ function.
  //
  //  \index{itk::Mesh!New()}
  //  \index{itk::Mesh!SetPoint()}
  //  \index{itk::Mesh!PointType}
  //  \index{itk::Mesh!Pointer}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  MeshType::Pointer  mesh = MeshType::New();

  typedef MeshType::PointType PointType;
  PointType point;

  const unsigned int numberOfPoints = 10;
  for(unsigned int id=0; id<numberOfPoints; id++)
    {
    point[0] = static_cast<PointType::ValueType>( id ); // x
    point[1] = vcl_log( static_cast<double>( id ) + 0.1 );    // y
    mesh->SetPoint( id, point );
    }
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  A set of line cells is created and associated with the existing points by
  //  using point identifiers. In this simple case, the point identifiers can
  //  be deduced from cell identifiers since the line cells are ordered in the
  //  same way.
  //
  //  \index{itk::AutoPointer!TakeOwnership()}
  //  \index{CellAutoPointer!TakeOwnership()}
  //  \index{CellType!creation}
  //  \index{itk::Mesh!SetCell()}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  CellType::CellAutoPointer line;
  const unsigned int numberOfCells = numberOfPoints-1;
  for(unsigned int cellId=0; cellId<numberOfCells; cellId++)
    {
    line.TakeOwnership(  new LineType  );
    line->SetPointId( 0, cellId   ); // first point
    line->SetPointId( 1, cellId+1 ); // second point
    mesh->SetCell( cellId, line );   // insert the cell
    }
  // Software Guide : EndCodeSnippet

  std::cout << "Points = " << mesh->GetNumberOfPoints() << std::endl;
  std::cout << "Cells  = " << mesh->GetNumberOfCells()  << std::endl;

  //  Software Guide : BeginLatex
  //
  //  Data associated with cells is inserted in the \doxygen{Mesh} by using
  //  the \code{SetCellData()} method.  It requires the user to provide an
  //  identifier and the value to be inserted. The identifier should match one
  //  of the inserted cells. In this simple example, the square of the cell
  //  identifier is used as cell data. Note the use of \code{static\_cast} to
  //  \code{PixelType} in the assignment.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  for(unsigned int cellId=0; cellId<numberOfCells; cellId++)
    {
    mesh->SetCellData( cellId, static_cast<PixelType>( cellId * cellId ) );
    }

  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  Cell data can be read from the Mesh with the
  //  \code{GetCellData()} method. It requires the user to provide the
  //  identifier of the cell for which the data is to be retrieved. The user
  //  should provide also a valid pointer to a location where the data can be
  //  copied.
  //
  //  \index{itk::Mesh!GetCellData()}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  for(unsigned int cellId=0; cellId<numberOfCells; cellId++)
    {
    PixelType value = static_cast<PixelType>(0.0);
    mesh->GetCellData( cellId, &value );
    std::cout << "Cell " << cellId << " = " << value << std::endl;
    }
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  Neither \code{SetCellData()} or \code{GetCellData()} are efficient ways
  //  to access cell data. More efficient access to cell data can be achieved
  //  by using the Iterators built into the \code{CellDataContainer}.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef MeshType::CellDataContainer::ConstIterator CellDataIterator;
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  Note that the \code{ConstIterator} is used here because the data is only
  //  going to be read.  This approach is exactly the same already illustrated
  //  for getting access to point data. The iterator to the first cell data
  //  item can be obtained with the \code{Begin()} method of the
  //  CellDataContainer. The past-end iterator is returned by the \code{End()}
  //  method. The cell data container itself can be obtained from the mesh with
  //  the method \code{GetCellData()}.
  //
  //  \index{itk::Mesh!Iterating cell data}
  //  \index{itk::Mesh!GetCellData()}
  //  \index{CellDataContainer!Begin()}
  //  \index{CellDataContainer!End()}
  //  \index{CellDataContainer!Iterator}
  //  \index{CellDataContainer!ConstIterator}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  CellDataIterator cellDataIterator  = mesh->GetCellData()->Begin();
  CellDataIterator end               = mesh->GetCellData()->End();
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  Finally a standard loop is used to iterate over all the cell data
  //  entries. Note the use of the \code{Value()} method used to get the actual
  //  value of the data entry. \code{PixelType} elements are copied into the
  //  local variable \code{cellValue}.
  //
  //  \index{CellDataIterator!Value()}
  //  \index{CellDataIterator!increment}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  while( cellDataIterator != end )
    {
    PixelType cellValue = cellDataIterator.Value();
    std::cout << cellValue << std::endl;
    ++cellDataIterator;
    }
  // Software Guide : EndCodeSnippet

  return 0;
}
<commit_msg>ENH: Replaced 0.1 with vnl_math::eps.<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  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.txt
 *
 *  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.
 *
 *=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

//  Software Guide : BeginLatex
//
//  In the same way that custom data can be associated with points in the mesh,
//  it is also possible to associate custom data with cells. The type of the
//  data associated with the cells can be different from the data type
//  associated with points. By default, however, these two types are the same.
//  The following example illustrates how to access data associated with cells.
//  The approach is analogous to the one used to access point data.
//
//  \index{itk::Mesh!Cell data}
//
//  Software Guide : EndLatex

//  Software Guide : BeginLatex
//
//  Consider the example of a mesh containing lines on which values are
//  associated with each line. The mesh and cell header files should be
//  included first.
//
//  Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
#include "itkMesh.h"
#include "itkLineCell.h"
// Software Guide : EndCodeSnippet

int main(int, char *[])
{
  //  Software Guide : BeginLatex
  //
  //  Then the PixelType is defined and the mesh type is instantiated with it.
  //
  //  \index{itk::Mesh!Instantiation}
  //  \index{itk::Mesh!PixelType}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef float                             PixelType;
  typedef itk::Mesh< PixelType, 2 >         MeshType;
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  The \doxygen{LineCell} type can now be instantiated using the traits
  //  taken from the Mesh.
  //
  //  \index{itk::LineCell!Instantiation}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef MeshType::CellType                CellType;
  typedef itk::LineCell< CellType >         LineType;
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  Let's now create a Mesh and insert some points into it. Note that the
  //  dimension of the points matches the dimension of the Mesh. Here we insert
  //  a sequence of points that look like a plot of the $\log()$ function.
  //  We add the vnl_math::eps values in oder to avoid numerical errors when
  //  the point id is zero. The value of vnl_math::eps is the smallest floating
  //  point number that can be represented in the current computer.
  //
  //  \index{itk::Mesh!New()}
  //  \index{itk::Mesh!SetPoint()}
  //  \index{itk::Mesh!PointType}
  //  \index{itk::Mesh!Pointer}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  MeshType::Pointer  mesh = MeshType::New();

  typedef MeshType::PointType PointType;
  PointType point;

  const unsigned int numberOfPoints = 10;
  for(unsigned int id=0; id<numberOfPoints; id++)
    {
    point[0] = static_cast<PointType::ValueType>( id ); // x
    point[1] = vcl_log( static_cast<double>( id ) + vnl_math::eps );    // y
    mesh->SetPoint( id, point );
    }
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  A set of line cells is created and associated with the existing points by
  //  using point identifiers. In this simple case, the point identifiers can
  //  be deduced from cell identifiers since the line cells are ordered in the
  //  same way.
  //
  //  \index{itk::AutoPointer!TakeOwnership()}
  //  \index{CellAutoPointer!TakeOwnership()}
  //  \index{CellType!creation}
  //  \index{itk::Mesh!SetCell()}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  CellType::CellAutoPointer line;
  const unsigned int numberOfCells = numberOfPoints-1;
  for(unsigned int cellId=0; cellId<numberOfCells; cellId++)
    {
    line.TakeOwnership(  new LineType  );
    line->SetPointId( 0, cellId   ); // first point
    line->SetPointId( 1, cellId+1 ); // second point
    mesh->SetCell( cellId, line );   // insert the cell
    }
  // Software Guide : EndCodeSnippet

  std::cout << "Points = " << mesh->GetNumberOfPoints() << std::endl;
  std::cout << "Cells  = " << mesh->GetNumberOfCells()  << std::endl;

  //  Software Guide : BeginLatex
  //
  //  Data associated with cells is inserted in the \doxygen{Mesh} by using
  //  the \code{SetCellData()} method.  It requires the user to provide an
  //  identifier and the value to be inserted. The identifier should match one
  //  of the inserted cells. In this simple example, the square of the cell
  //  identifier is used as cell data. Note the use of \code{static\_cast} to
  //  \code{PixelType} in the assignment.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  for(unsigned int cellId=0; cellId<numberOfCells; cellId++)
    {
    mesh->SetCellData( cellId, static_cast<PixelType>( cellId * cellId ) );
    }

  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  Cell data can be read from the Mesh with the
  //  \code{GetCellData()} method. It requires the user to provide the
  //  identifier of the cell for which the data is to be retrieved. The user
  //  should provide also a valid pointer to a location where the data can be
  //  copied.
  //
  //  \index{itk::Mesh!GetCellData()}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  for(unsigned int cellId=0; cellId<numberOfCells; cellId++)
    {
    PixelType value = static_cast<PixelType>(0.0);
    mesh->GetCellData( cellId, &value );
    std::cout << "Cell " << cellId << " = " << value << std::endl;
    }
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  Neither \code{SetCellData()} or \code{GetCellData()} are efficient ways
  //  to access cell data. More efficient access to cell data can be achieved
  //  by using the Iterators built into the \code{CellDataContainer}.
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef MeshType::CellDataContainer::ConstIterator CellDataIterator;
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  Note that the \code{ConstIterator} is used here because the data is only
  //  going to be read.  This approach is exactly the same already illustrated
  //  for getting access to point data. The iterator to the first cell data
  //  item can be obtained with the \code{Begin()} method of the
  //  CellDataContainer. The past-end iterator is returned by the \code{End()}
  //  method. The cell data container itself can be obtained from the mesh with
  //  the method \code{GetCellData()}.
  //
  //  \index{itk::Mesh!Iterating cell data}
  //  \index{itk::Mesh!GetCellData()}
  //  \index{CellDataContainer!Begin()}
  //  \index{CellDataContainer!End()}
  //  \index{CellDataContainer!Iterator}
  //  \index{CellDataContainer!ConstIterator}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  CellDataIterator cellDataIterator  = mesh->GetCellData()->Begin();
  CellDataIterator end               = mesh->GetCellData()->End();
  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  //
  //  Finally a standard loop is used to iterate over all the cell data
  //  entries. Note the use of the \code{Value()} method used to get the actual
  //  value of the data entry. \code{PixelType} elements are copied into the
  //  local variable \code{cellValue}.
  //
  //  \index{CellDataIterator!Value()}
  //  \index{CellDataIterator!increment}
  //
  //  Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  while( cellDataIterator != end )
    {
    PixelType cellValue = cellDataIterator.Value();
    std::cout << cellValue << std::endl;
    ++cellDataIterator;
    }
  // Software Guide : EndCodeSnippet

  return 0;
}
<|endoftext|>