void initializeFilter(ParameterTypes... parameters) {
     filter.reset(new FilterType(parameters...));
 }
示例#2
0
文件: ieqpro.cpp 项目: mp77/indi
void ISNewText(	const char *dev, const char *name, char *texts[], char *names[], int num)
{
        scope->ISNewText(dev, name, texts, names, num);
}
示例#3
0
文件: ieqpro.cpp 项目: mp77/indi
void ISSnoopDevice (XMLEle *root)
{
   scope->ISSnoopDevice(root);
}
示例#4
0
bool IsRealTimeStream(void)
{
  return !g_pvr_client->is_timeshifting();
}
示例#5
0
文件: ieqpro.cpp 项目: mp77/indi
void ISGetProperties(const char *dev)
{
        scope->ISGetProperties(dev);
}
示例#6
0
int GetChannelsAmount(void)
{
  return g_pvr_client->get_channels_num();
}
示例#7
0
void CloseLiveStream(void)
{
  if (XBMC)
    XBMC->Log(LOG_DEBUG, "CloseLiveStream");
  g_pvr_client->destroy_session();
}
示例#8
0
void VertexManager::DestroyDeviceObjects()
{
  s_vertexBuffer.reset();
  s_indexBuffer.reset();
}
示例#9
0
文件: Sprite.hpp 项目: SgtCoDFish/APG
	explicit Sprite(const std::unique_ptr<Texture> &texture) :
			Sprite(texture.get()) {
	}
示例#10
0
void Controller::sendRequests() {
    // Connector::connect()

    try {
        connector_ptr_->connect(num_connect_attempts_);
    } catch (PCPClient::connection_config_error& e) {
        std::string err_msg { "failed to configure WebSocket: " };
        throw controller_error { err_msg + e.what() };
    } catch (PCPClient::connection_fatal_error& e) {
        std::string err_msg { "failed to connect to " + BROKER_URL + " or "
                              + FAILOVER_URL + " after "
                              + std::to_string(num_connect_attempts_)
                              + " attempts: " };
        throw controller_error { err_msg + e.what() };
    }

    // Connector::isConnected()

    if (connector_ptr_->isConnected()) {
        std::cout << "Successfully connected\n";
    } else {
        // The connection has dropped; we can't send anything
        throw controller_error { "connection dropped" };
    }

    // Send a valid request - a response is expected

    leatherman::json_container::JsonContainer track {
        "{\"artist\" : \"Captain Beefheart\"}" };
    leatherman::json_container::JsonContainer valid_request {};
    valid_request.set<leatherman::json_container::JsonContainer>("request", track);
    valid_request.set<std::string>("details", "please send some good music");

    std::vector<std::string> endpoints { "pcp://*/" + AGENT_CLIENT_TYPE };

    try {
        auto id = connector_ptr_->send(endpoints,
                                       REQUEST_SCHEMA_NAME,
                                       MSG_TIMEOUT_S,
                                       valid_request);
        std::cout << "Valid request message sent; message id: " << id << "\n";
    } catch (PCPClient::connection_processing_error& e) {
        std::string err_msg { "failed to send the request message: " };
        throw controller_error { err_msg + e.what() };
    }

    // Send an invalid request - an error message should arrive

    leatherman::json_container::JsonContainer bad_json {
        "{\"genre\" : \"experimental rock\"}" };
    leatherman::json_container::JsonContainer bad_request {};
    bad_request.set<leatherman::json_container::JsonContainer>("request", bad_json);
    bad_request.set<std::string>("details", "I'm not sure about this");

    try {
        auto id = connector_ptr_->send(endpoints,
                                       REQUEST_SCHEMA_NAME,
                                       MSG_TIMEOUT_S,
                                       bad_request);
        std::cout << "Bad request message sent; message id: " << id << "\n";
    } catch (PCPClient::connection_processing_error& e) {
        std::string err_msg { "failed to send the request message: " };
        throw controller_error { err_msg + e.what() };
    }

    // Send an inventory request to the broker

    leatherman::json_container::JsonContainer inventory_request {};
    std::vector<std::string> query { "cth://*/" + AGENT_CLIENT_TYPE };
    inventory_request.set<std::vector<std::string>>("query", query);

    try {
        // NB: use "cth:///server" with 3 '/' as the broker URI
        auto id  = connector_ptr_->send(std::vector<std::string> { "cth:///server" },
                                        PCPClient::Protocol::INVENTORY_REQ_TYPE,
                                        MSG_TIMEOUT_S,
                                        inventory_request);
        std::cout << "Inventory request message sent; message id: " << id << "\n";
    } catch (PCPClient::connection_processing_error& e) {
        std::string err_msg { "failed to send the inventory request message: " };
        throw controller_error { err_msg + e.what() };
    }

    // Wait for the response and error messages
    sleep(2);
}
示例#11
0
namespace OGL
{
// This are the initially requested size for the buffers expressed in bytes
const u32 MAX_IBUFFER_SIZE = 2 * 1024 * 1024;
const u32 MAX_VBUFFER_SIZE = 32 * 1024 * 1024;

static std::unique_ptr<StreamBuffer> s_vertexBuffer;
static std::unique_ptr<StreamBuffer> s_indexBuffer;
static size_t s_baseVertex;
static size_t s_index_offset;

VertexManager::VertexManager() : m_cpu_v_buffer(MAX_VBUFFER_SIZE), m_cpu_i_buffer(MAX_IBUFFER_SIZE)
{
  CreateDeviceObjects();
}

VertexManager::~VertexManager()
{
  DestroyDeviceObjects();
}

void VertexManager::CreateDeviceObjects()
{
  s_vertexBuffer = StreamBuffer::Create(GL_ARRAY_BUFFER, MAX_VBUFFER_SIZE);
  m_vertex_buffers = s_vertexBuffer->m_buffer;

  s_indexBuffer = StreamBuffer::Create(GL_ELEMENT_ARRAY_BUFFER, MAX_IBUFFER_SIZE);
  m_index_buffers = s_indexBuffer->m_buffer;

  m_last_vao = 0;
}

void VertexManager::DestroyDeviceObjects()
{
  s_vertexBuffer.reset();
  s_indexBuffer.reset();
}

void VertexManager::PrepareDrawBuffers(u32 stride)
{
  u32 vertex_data_size = IndexGenerator::GetNumVerts() * stride;
  u32 index_data_size = IndexGenerator::GetIndexLen() * sizeof(u16);

  s_vertexBuffer->Unmap(vertex_data_size);
  s_indexBuffer->Unmap(index_data_size);

  ADDSTAT(stats.thisFrame.bytesVertexStreamed, vertex_data_size);
  ADDSTAT(stats.thisFrame.bytesIndexStreamed, index_data_size);
}

void VertexManager::ResetBuffer(u32 stride)
{
  if (m_cull_all)
  {
    // This buffer isn't getting sent to the GPU. Just allocate it on the cpu.
    m_cur_buffer_pointer = m_base_buffer_pointer = m_cpu_v_buffer.data();
    m_end_buffer_pointer = m_base_buffer_pointer + m_cpu_v_buffer.size();

    IndexGenerator::Start((u16*)m_cpu_i_buffer.data());
  }
  else
  {
    auto buffer = s_vertexBuffer->Map(MAXVBUFFERSIZE, stride);
    m_cur_buffer_pointer = m_base_buffer_pointer = buffer.first;
    m_end_buffer_pointer = buffer.first + MAXVBUFFERSIZE;
    s_baseVertex = buffer.second / stride;

    buffer = s_indexBuffer->Map(MAXIBUFFERSIZE * sizeof(u16));
    IndexGenerator::Start((u16*)buffer.first);
    s_index_offset = buffer.second;
  }
}

void VertexManager::Draw(u32 stride)
{
  u32 index_size = IndexGenerator::GetIndexLen();
  u32 max_index = IndexGenerator::GetNumVerts();
  GLenum primitive_mode = 0;

  switch (m_current_primitive_type)
  {
  case PRIMITIVE_POINTS:
    primitive_mode = GL_POINTS;
    glDisable(GL_CULL_FACE);
    break;
  case PRIMITIVE_LINES:
    primitive_mode = GL_LINES;
    glDisable(GL_CULL_FACE);
    break;
  case PRIMITIVE_TRIANGLES:
    primitive_mode =
        g_ActiveConfig.backend_info.bSupportsPrimitiveRestart ? GL_TRIANGLE_STRIP : GL_TRIANGLES;
    break;
  }

  if (g_ogl_config.bSupportsGLBaseVertex)
  {
    glDrawRangeElementsBaseVertex(primitive_mode, 0, max_index, index_size, GL_UNSIGNED_SHORT,
                                  (u8*)nullptr + s_index_offset, (GLint)s_baseVertex);
  }
  else
  {
    glDrawRangeElements(primitive_mode, 0, max_index, index_size, GL_UNSIGNED_SHORT,
                        (u8*)nullptr + s_index_offset);
  }

  INCSTAT(stats.thisFrame.numDrawCalls);

  if (m_current_primitive_type != PRIMITIVE_TRIANGLES)
    static_cast<Renderer*>(g_renderer.get())->SetGenerationMode();
}

void VertexManager::vFlush(bool useDstAlpha)
{
  GLVertexFormat* nativeVertexFmt = (GLVertexFormat*)VertexLoaderManager::GetCurrentVertexFormat();
  u32 stride = nativeVertexFmt->GetVertexStride();

  if (m_last_vao != nativeVertexFmt->VAO)
  {
    glBindVertexArray(nativeVertexFmt->VAO);
    m_last_vao = nativeVertexFmt->VAO;
  }

  PrepareDrawBuffers(stride);

  // Makes sure we can actually do Dual source blending
  bool dualSourcePossible = g_ActiveConfig.backend_info.bSupportsDualSourceBlend;

  // If host supports GL_ARB_blend_func_extended, we can do dst alpha in
  // the same pass as regular rendering.
  if (useDstAlpha && dualSourcePossible)
  {
    ProgramShaderCache::SetShader(DSTALPHA_DUAL_SOURCE_BLEND, m_current_primitive_type);
  }
  else
  {
    ProgramShaderCache::SetShader(DSTALPHA_NONE, m_current_primitive_type);
  }

  // upload global constants
  ProgramShaderCache::UploadConstants();

  // setup the pointers
  nativeVertexFmt->SetupVertexPointers();

  Draw(stride);

  // run through vertex groups again to set alpha
  if (useDstAlpha && !dualSourcePossible)
  {
    ProgramShaderCache::SetShader(DSTALPHA_ALPHA_PASS, m_current_primitive_type);

    // only update alpha
    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);

    glDisable(GL_BLEND);

    Draw(stride);

    // restore color mask
    g_renderer->SetColorMask();

    if (bpmem.blendmode.blendenable || bpmem.blendmode.subtract)
      glEnable(GL_BLEND);
  }

#if defined(_DEBUG) || defined(DEBUGFAST)
  if (g_ActiveConfig.iLog & CONF_SAVESHADERS)
  {
    // save the shaders
    ProgramShaderCache::PCacheEntry prog = ProgramShaderCache::GetShaderProgram();
    std::string filename = StringFromFormat(
        "%sps%.3d.txt", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId);
    std::ofstream fps;
    OpenFStream(fps, filename, std::ios_base::out);
    fps << prog.shader.strpprog;

    filename = StringFromFormat("%svs%.3d.txt", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(),
                                g_ActiveConfig.iSaveTargetId);
    std::ofstream fvs;
    OpenFStream(fvs, filename, std::ios_base::out);
    fvs << prog.shader.strvprog;
  }

  if (g_ActiveConfig.iLog & CONF_SAVETARGETS)
  {
    std::string filename =
        StringFromFormat("%starg%.3d.png", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(),
                         g_ActiveConfig.iSaveTargetId);
    TargetRectangle tr;
    tr.left = 0;
    tr.right = Renderer::GetTargetWidth();
    tr.top = 0;
    tr.bottom = Renderer::GetTargetHeight();
    g_renderer->SaveScreenshot(filename, tr);
  }
#endif
  g_Config.iSaveTargetId++;

  ClearEFBCache();
}

}  // namespace
示例#12
0
ssize_t UdpTransport::SendSinglePacketHelper(
        Header* header, const uint8_t* tx_data, size_t tx_length, uint8_t* rx_data,
        size_t rx_length, const int attempts, std::string* error) {
    ssize_t total_data_bytes = 0;
    error->clear();

    int attempts_left = attempts;
    while (attempts_left > 0) {
        if (!socket_->Send({{header->bytes(), kHeaderSize}, {tx_data, tx_length}})) {
            *error = Socket::GetErrorMessage();
            return -1;
        }

        // Keep receiving until we get a matching response or we timeout.
        ssize_t bytes = 0;
        do {
            bytes = socket_->Receive(rx_packet_.data(), rx_packet_.size(), kResponseTimeoutMs);
            if (bytes == -1) {
                if (socket_->ReceiveTimedOut()) {
                    break;
                }
                *error = Socket::GetErrorMessage();
                return -1;
            } else if (bytes < static_cast<ssize_t>(kHeaderSize)) {
                *error = "protocol error: incomplete header";
                return -1;
            }
        } while (!header->Matches(rx_packet_.data()));

        if (socket_->ReceiveTimedOut()) {
            --attempts_left;
            continue;
        }
        ++sequence_;

        // Save to |error| or |rx_data| as appropriate.
        if (rx_packet_[kIndexId] == kIdError) {
            error->append(rx_packet_.data() + kHeaderSize, rx_packet_.data() + bytes);
        } else {
            total_data_bytes += bytes - kHeaderSize;
            size_t rx_data_bytes = std::min<size_t>(bytes - kHeaderSize, rx_length);
            if (rx_data_bytes > 0) {
                memcpy(rx_data, rx_packet_.data() + kHeaderSize, rx_data_bytes);
                rx_data += rx_data_bytes;
                rx_length -= rx_data_bytes;
            }
        }

        // If the response has a continuation flag we need to prompt for more data by sending
        // an empty packet.
        if (rx_packet_[kIndexFlags] & kFlagContinuation) {
            // We got a valid response so reset our attempt counter.
            attempts_left = attempts;
            header->Set(rx_packet_[kIndexId], sequence_, kFlagNone);
            tx_data = nullptr;
            tx_length = 0;
            continue;
        }

        break;
    }

    if (attempts_left <= 0) {
        *error = "no response from target";
        return -1;
    }

    if (rx_packet_[kIndexId] == kIdError) {
        *error = "target reported error: " + *error;
        return -1;
    }

    return total_data_bytes;
}
示例#13
0
文件: main.cpp 项目: CCJY/coliru
std::unique_ptr<T> downcast_unique(std::unique_ptr<U> p)
{
    return std::unique_ptr<T>(dynamic_cast<T*>(p.release()));
}
 DestinationImageType transformImage() override {
     return filter->apply(*this->sourceImage);
 }
示例#15
0
文件: hid.cpp 项目: JayFoxRox/citra
static void UpdatePadCallback(u64 userdata, int cycles_late) {
    SharedMem* mem = reinterpret_cast<SharedMem*>(shared_mem->GetPointer());

    if (is_device_reload_pending.exchange(false))
        LoadInputDevices();

    PadState state;
    using namespace Settings::NativeButton;
    state.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus());
    state.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus());
    state.x.Assign(buttons[X - BUTTON_HID_BEGIN]->GetStatus());
    state.y.Assign(buttons[Y - BUTTON_HID_BEGIN]->GetStatus());
    state.right.Assign(buttons[Right - BUTTON_HID_BEGIN]->GetStatus());
    state.left.Assign(buttons[Left - BUTTON_HID_BEGIN]->GetStatus());
    state.up.Assign(buttons[Up - BUTTON_HID_BEGIN]->GetStatus());
    state.down.Assign(buttons[Down - BUTTON_HID_BEGIN]->GetStatus());
    state.l.Assign(buttons[L - BUTTON_HID_BEGIN]->GetStatus());
    state.r.Assign(buttons[R - BUTTON_HID_BEGIN]->GetStatus());
    state.start.Assign(buttons[Start - BUTTON_HID_BEGIN]->GetStatus());
    state.select.Assign(buttons[Select - BUTTON_HID_BEGIN]->GetStatus());

    // Get current circle pad position and update circle pad direction
    float circle_pad_x_f, circle_pad_y_f;
    std::tie(circle_pad_x_f, circle_pad_y_f) = circle_pad->GetStatus();
    constexpr int MAX_CIRCLEPAD_POS = 0x9C; // Max value for a circle pad position
    s16 circle_pad_x = static_cast<s16>(circle_pad_x_f * MAX_CIRCLEPAD_POS);
    s16 circle_pad_y = static_cast<s16>(circle_pad_y_f * MAX_CIRCLEPAD_POS);
    const DirectionState direction = GetStickDirectionState(circle_pad_x, circle_pad_y);
    state.circle_up.Assign(direction.up);
    state.circle_down.Assign(direction.down);
    state.circle_left.Assign(direction.left);
    state.circle_right.Assign(direction.right);

    mem->pad.current_state.hex = state.hex;
    mem->pad.index = next_pad_index;
    next_pad_index = (next_pad_index + 1) % mem->pad.entries.size();

    // Get the previous Pad state
    u32 last_entry_index = (mem->pad.index - 1) % mem->pad.entries.size();
    PadState old_state = mem->pad.entries[last_entry_index].current_state;

    // Compute bitmask with 1s for bits different from the old state
    PadState changed = {{(state.hex ^ old_state.hex)}};

    // Get the current Pad entry
    PadDataEntry& pad_entry = mem->pad.entries[mem->pad.index];

    // Update entry properties
    pad_entry.current_state.hex = state.hex;
    pad_entry.delta_additions.hex = changed.hex & state.hex;
    pad_entry.delta_removals.hex = changed.hex & old_state.hex;
    pad_entry.circle_pad_x = circle_pad_x;
    pad_entry.circle_pad_y = circle_pad_y;

    // If we just updated index 0, provide a new timestamp
    if (mem->pad.index == 0) {
        mem->pad.index_reset_ticks_previous = mem->pad.index_reset_ticks;
        mem->pad.index_reset_ticks = (s64)CoreTiming::GetTicks();
    }

    mem->touch.index = next_touch_index;
    next_touch_index = (next_touch_index + 1) % mem->touch.entries.size();

    // Get the current touch entry
    TouchDataEntry& touch_entry = mem->touch.entries[mem->touch.index];
    bool pressed = false;
    float x, y;
    std::tie(x, y, pressed) = touch_device->GetStatus();
    touch_entry.x = static_cast<u16>(x * Core::kScreenBottomWidth);
    touch_entry.y = static_cast<u16>(y * Core::kScreenBottomHeight);
    touch_entry.valid.Assign(pressed ? 1 : 0);

    // TODO(bunnei): We're not doing anything with offset 0xA8 + 0x18 of HID SharedMemory, which
    // supposedly is "Touch-screen entry, which contains the raw coordinate data prior to being
    // converted to pixel coordinates." (http://3dbrew.org/wiki/HID_Shared_Memory#Offset_0xA8).

    // If we just updated index 0, provide a new timestamp
    if (mem->touch.index == 0) {
        mem->touch.index_reset_ticks_previous = mem->touch.index_reset_ticks;
        mem->touch.index_reset_ticks = (s64)CoreTiming::GetTicks();
    }

    // Signal both handles when there's an update to Pad or touch
    event_pad_or_touch_1->Signal();
    event_pad_or_touch_2->Signal();

    // Reschedule recurrent event
    CoreTiming::ScheduleEvent(pad_update_ticks - cycles_late, pad_update_event);
}
示例#16
0
文件: Sprite.hpp 项目: SgtCoDFish/APG
	explicit Sprite(const std::unique_ptr<Texture> &texture, int32_t texX, int32_t texY, int32_t width,
					int32_t height) :
			Sprite(texture.get(), texX, texY, width, height) {
	}
示例#17
0
文件: hid.cpp 项目: JayFoxRox/citra
namespace HID {

// Handle to shared memory region designated to HID_User service
static Kernel::SharedPtr<Kernel::SharedMemory> shared_mem;

// Event handles
static Kernel::SharedPtr<Kernel::Event> event_pad_or_touch_1;
static Kernel::SharedPtr<Kernel::Event> event_pad_or_touch_2;
static Kernel::SharedPtr<Kernel::Event> event_accelerometer;
static Kernel::SharedPtr<Kernel::Event> event_gyroscope;
static Kernel::SharedPtr<Kernel::Event> event_debug_pad;

static u32 next_pad_index;
static u32 next_touch_index;
static u32 next_accelerometer_index;
static u32 next_gyroscope_index;

static int enable_accelerometer_count; // positive means enabled
static int enable_gyroscope_count;     // positive means enabled

static int pad_update_event;
static int accelerometer_update_event;
static int gyroscope_update_event;

// Updating period for each HID device. These empirical values are measured from a 11.2 3DS.
constexpr u64 pad_update_ticks = BASE_CLOCK_RATE_ARM11 / 234;
constexpr u64 accelerometer_update_ticks = BASE_CLOCK_RATE_ARM11 / 104;
constexpr u64 gyroscope_update_ticks = BASE_CLOCK_RATE_ARM11 / 101;

constexpr float accelerometer_coef = 512.0f; // measured from hw test result
constexpr float gyroscope_coef = 14.375f; // got from hwtest GetGyroscopeLowRawToDpsCoefficient call

static std::atomic<bool> is_device_reload_pending;
static std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID>
    buttons;
static std::unique_ptr<Input::AnalogDevice> circle_pad;
static std::unique_ptr<Input::MotionDevice> motion_device;
static std::unique_ptr<Input::TouchDevice> touch_device;

DirectionState GetStickDirectionState(s16 circle_pad_x, s16 circle_pad_y) {
    // 30 degree and 60 degree are angular thresholds for directions
    constexpr float TAN30 = 0.577350269f;
    constexpr float TAN60 = 1 / TAN30;
    // a circle pad radius greater than 40 will trigger circle pad direction
    constexpr int CIRCLE_PAD_THRESHOLD_SQUARE = 40 * 40;
    DirectionState state{false, false, false, false};

    if (circle_pad_x * circle_pad_x + circle_pad_y * circle_pad_y > CIRCLE_PAD_THRESHOLD_SQUARE) {
        float t = std::abs(static_cast<float>(circle_pad_y) / circle_pad_x);

        if (circle_pad_x != 0 && t < TAN60) {
            if (circle_pad_x > 0)
                state.right = true;
            else
                state.left = true;
        }

        if (circle_pad_x == 0 || t > TAN30) {
            if (circle_pad_y > 0)
                state.up = true;
            else
                state.down = true;
        }
    }

    return state;
}

static void LoadInputDevices() {
    std::transform(Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN,
                   Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_END,
                   buttons.begin(), Input::CreateDevice<Input::ButtonDevice>);
    circle_pad = Input::CreateDevice<Input::AnalogDevice>(
        Settings::values.analogs[Settings::NativeAnalog::CirclePad]);
    motion_device = Input::CreateDevice<Input::MotionDevice>(Settings::values.motion_device);
    touch_device = Input::CreateDevice<Input::TouchDevice>(Settings::values.touch_device);
}

static void UnloadInputDevices() {
    for (auto& button : buttons) {
        button.reset();
    }
    circle_pad.reset();
    motion_device.reset();
    touch_device.reset();
}

static void UpdatePadCallback(u64 userdata, int cycles_late) {
    SharedMem* mem = reinterpret_cast<SharedMem*>(shared_mem->GetPointer());

    if (is_device_reload_pending.exchange(false))
        LoadInputDevices();

    PadState state;
    using namespace Settings::NativeButton;
    state.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus());
    state.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus());
    state.x.Assign(buttons[X - BUTTON_HID_BEGIN]->GetStatus());
    state.y.Assign(buttons[Y - BUTTON_HID_BEGIN]->GetStatus());
    state.right.Assign(buttons[Right - BUTTON_HID_BEGIN]->GetStatus());
    state.left.Assign(buttons[Left - BUTTON_HID_BEGIN]->GetStatus());
    state.up.Assign(buttons[Up - BUTTON_HID_BEGIN]->GetStatus());
    state.down.Assign(buttons[Down - BUTTON_HID_BEGIN]->GetStatus());
    state.l.Assign(buttons[L - BUTTON_HID_BEGIN]->GetStatus());
    state.r.Assign(buttons[R - BUTTON_HID_BEGIN]->GetStatus());
    state.start.Assign(buttons[Start - BUTTON_HID_BEGIN]->GetStatus());
    state.select.Assign(buttons[Select - BUTTON_HID_BEGIN]->GetStatus());

    // Get current circle pad position and update circle pad direction
    float circle_pad_x_f, circle_pad_y_f;
    std::tie(circle_pad_x_f, circle_pad_y_f) = circle_pad->GetStatus();
    constexpr int MAX_CIRCLEPAD_POS = 0x9C; // Max value for a circle pad position
    s16 circle_pad_x = static_cast<s16>(circle_pad_x_f * MAX_CIRCLEPAD_POS);
    s16 circle_pad_y = static_cast<s16>(circle_pad_y_f * MAX_CIRCLEPAD_POS);
    const DirectionState direction = GetStickDirectionState(circle_pad_x, circle_pad_y);
    state.circle_up.Assign(direction.up);
    state.circle_down.Assign(direction.down);
    state.circle_left.Assign(direction.left);
    state.circle_right.Assign(direction.right);

    mem->pad.current_state.hex = state.hex;
    mem->pad.index = next_pad_index;
    next_pad_index = (next_pad_index + 1) % mem->pad.entries.size();

    // Get the previous Pad state
    u32 last_entry_index = (mem->pad.index - 1) % mem->pad.entries.size();
    PadState old_state = mem->pad.entries[last_entry_index].current_state;

    // Compute bitmask with 1s for bits different from the old state
    PadState changed = {{(state.hex ^ old_state.hex)}};

    // Get the current Pad entry
    PadDataEntry& pad_entry = mem->pad.entries[mem->pad.index];

    // Update entry properties
    pad_entry.current_state.hex = state.hex;
    pad_entry.delta_additions.hex = changed.hex & state.hex;
    pad_entry.delta_removals.hex = changed.hex & old_state.hex;
    pad_entry.circle_pad_x = circle_pad_x;
    pad_entry.circle_pad_y = circle_pad_y;

    // If we just updated index 0, provide a new timestamp
    if (mem->pad.index == 0) {
        mem->pad.index_reset_ticks_previous = mem->pad.index_reset_ticks;
        mem->pad.index_reset_ticks = (s64)CoreTiming::GetTicks();
    }

    mem->touch.index = next_touch_index;
    next_touch_index = (next_touch_index + 1) % mem->touch.entries.size();

    // Get the current touch entry
    TouchDataEntry& touch_entry = mem->touch.entries[mem->touch.index];
    bool pressed = false;
    float x, y;
    std::tie(x, y, pressed) = touch_device->GetStatus();
    touch_entry.x = static_cast<u16>(x * Core::kScreenBottomWidth);
    touch_entry.y = static_cast<u16>(y * Core::kScreenBottomHeight);
    touch_entry.valid.Assign(pressed ? 1 : 0);

    // TODO(bunnei): We're not doing anything with offset 0xA8 + 0x18 of HID SharedMemory, which
    // supposedly is "Touch-screen entry, which contains the raw coordinate data prior to being
    // converted to pixel coordinates." (http://3dbrew.org/wiki/HID_Shared_Memory#Offset_0xA8).

    // If we just updated index 0, provide a new timestamp
    if (mem->touch.index == 0) {
        mem->touch.index_reset_ticks_previous = mem->touch.index_reset_ticks;
        mem->touch.index_reset_ticks = (s64)CoreTiming::GetTicks();
    }

    // Signal both handles when there's an update to Pad or touch
    event_pad_or_touch_1->Signal();
    event_pad_or_touch_2->Signal();

    // Reschedule recurrent event
    CoreTiming::ScheduleEvent(pad_update_ticks - cycles_late, pad_update_event);
}

static void UpdateAccelerometerCallback(u64 userdata, int cycles_late) {
    SharedMem* mem = reinterpret_cast<SharedMem*>(shared_mem->GetPointer());

    mem->accelerometer.index = next_accelerometer_index;
    next_accelerometer_index = (next_accelerometer_index + 1) % mem->accelerometer.entries.size();

    Math::Vec3<float> accel;
    std::tie(accel, std::ignore) = motion_device->GetStatus();
    accel *= accelerometer_coef;
    // TODO(wwylele): do a time stretch like the one in UpdateGyroscopeCallback
    // The time stretch formula should be like
    // stretched_vector = (raw_vector - gravity) * stretch_ratio + gravity

    AccelerometerDataEntry& accelerometer_entry =
        mem->accelerometer.entries[mem->accelerometer.index];

    accelerometer_entry.x = static_cast<s16>(accel.x);
    accelerometer_entry.y = static_cast<s16>(accel.y);
    accelerometer_entry.z = static_cast<s16>(accel.z);

    // Make up "raw" entry
    // TODO(wwylele):
    // From hardware testing, the raw_entry values are approximately, but not exactly, as twice as
    // corresponding entries (or with a minus sign). It may caused by system calibration to the
    // accelerometer. Figure out how it works, or, if no game reads raw_entry, the following three
    // lines can be removed and leave raw_entry unimplemented.
    mem->accelerometer.raw_entry.x = -2 * accelerometer_entry.x;
    mem->accelerometer.raw_entry.z = 2 * accelerometer_entry.y;
    mem->accelerometer.raw_entry.y = -2 * accelerometer_entry.z;

    // If we just updated index 0, provide a new timestamp
    if (mem->accelerometer.index == 0) {
        mem->accelerometer.index_reset_ticks_previous = mem->accelerometer.index_reset_ticks;
        mem->accelerometer.index_reset_ticks = (s64)CoreTiming::GetTicks();
    }

    event_accelerometer->Signal();

    // Reschedule recurrent event
    CoreTiming::ScheduleEvent(accelerometer_update_ticks - cycles_late, accelerometer_update_event);
}

static void UpdateGyroscopeCallback(u64 userdata, int cycles_late) {
    SharedMem* mem = reinterpret_cast<SharedMem*>(shared_mem->GetPointer());

    mem->gyroscope.index = next_gyroscope_index;
    next_gyroscope_index = (next_gyroscope_index + 1) % mem->gyroscope.entries.size();

    GyroscopeDataEntry& gyroscope_entry = mem->gyroscope.entries[mem->gyroscope.index];

    Math::Vec3<float> gyro;
    std::tie(std::ignore, gyro) = motion_device->GetStatus();
    double stretch = Core::System::GetInstance().perf_stats.GetLastFrameTimeScale();
    gyro *= gyroscope_coef * static_cast<float>(stretch);
    gyroscope_entry.x = static_cast<s16>(gyro.x);
    gyroscope_entry.y = static_cast<s16>(gyro.y);
    gyroscope_entry.z = static_cast<s16>(gyro.z);

    // Make up "raw" entry
    mem->gyroscope.raw_entry.x = gyroscope_entry.x;
    mem->gyroscope.raw_entry.z = -gyroscope_entry.y;
    mem->gyroscope.raw_entry.y = gyroscope_entry.z;

    // If we just updated index 0, provide a new timestamp
    if (mem->gyroscope.index == 0) {
        mem->gyroscope.index_reset_ticks_previous = mem->gyroscope.index_reset_ticks;
        mem->gyroscope.index_reset_ticks = (s64)CoreTiming::GetTicks();
    }

    event_gyroscope->Signal();

    // Reschedule recurrent event
    CoreTiming::ScheduleEvent(gyroscope_update_ticks - cycles_late, gyroscope_update_event);
}

void GetIPCHandles(Service::Interface* self) {
    u32* cmd_buff = Kernel::GetCommandBuffer();

    cmd_buff[1] = 0;          // No error
    cmd_buff[2] = 0x14000000; // IPC Command Structure translate-header
    // TODO(yuriks): Return error from SendSyncRequest is this fails (part of IPC marshalling)
    cmd_buff[3] = Kernel::g_handle_table.Create(Service::HID::shared_mem).Unwrap();
    cmd_buff[4] = Kernel::g_handle_table.Create(Service::HID::event_pad_or_touch_1).Unwrap();
    cmd_buff[5] = Kernel::g_handle_table.Create(Service::HID::event_pad_or_touch_2).Unwrap();
    cmd_buff[6] = Kernel::g_handle_table.Create(Service::HID::event_accelerometer).Unwrap();
    cmd_buff[7] = Kernel::g_handle_table.Create(Service::HID::event_gyroscope).Unwrap();
    cmd_buff[8] = Kernel::g_handle_table.Create(Service::HID::event_debug_pad).Unwrap();
}

void EnableAccelerometer(Service::Interface* self) {
    u32* cmd_buff = Kernel::GetCommandBuffer();

    ++enable_accelerometer_count;

    // Schedules the accelerometer update event if the accelerometer was just enabled
    if (enable_accelerometer_count == 1) {
        CoreTiming::ScheduleEvent(accelerometer_update_ticks, accelerometer_update_event);
    }

    cmd_buff[1] = RESULT_SUCCESS.raw;

    LOG_DEBUG(Service_HID, "called");
}

void DisableAccelerometer(Service::Interface* self) {
    u32* cmd_buff = Kernel::GetCommandBuffer();

    --enable_accelerometer_count;

    // Unschedules the accelerometer update event if the accelerometer was just disabled
    if (enable_accelerometer_count == 0) {
        CoreTiming::UnscheduleEvent(accelerometer_update_event, 0);
    }

    cmd_buff[1] = RESULT_SUCCESS.raw;

    LOG_DEBUG(Service_HID, "called");
}

void EnableGyroscopeLow(Service::Interface* self) {
    u32* cmd_buff = Kernel::GetCommandBuffer();

    ++enable_gyroscope_count;

    // Schedules the gyroscope update event if the gyroscope was just enabled
    if (enable_gyroscope_count == 1) {
        CoreTiming::ScheduleEvent(gyroscope_update_ticks, gyroscope_update_event);
    }

    cmd_buff[1] = RESULT_SUCCESS.raw;

    LOG_DEBUG(Service_HID, "called");
}

void DisableGyroscopeLow(Service::Interface* self) {
    u32* cmd_buff = Kernel::GetCommandBuffer();

    --enable_gyroscope_count;

    // Unschedules the gyroscope update event if the gyroscope was just disabled
    if (enable_gyroscope_count == 0) {
        CoreTiming::UnscheduleEvent(gyroscope_update_event, 0);
    }

    cmd_buff[1] = RESULT_SUCCESS.raw;

    LOG_DEBUG(Service_HID, "called");
}

void GetGyroscopeLowRawToDpsCoefficient(Service::Interface* self) {
    u32* cmd_buff = Kernel::GetCommandBuffer();

    cmd_buff[1] = RESULT_SUCCESS.raw;

    f32 coef = gyroscope_coef;
    memcpy(&cmd_buff[2], &coef, 4);
}

void GetGyroscopeLowCalibrateParam(Service::Interface* self) {
    u32* cmd_buff = Kernel::GetCommandBuffer();

    cmd_buff[1] = RESULT_SUCCESS.raw;

    const s16 param_unit = 6700; // an approximate value taken from hw
    GyroscopeCalibrateParam param = {
        {0, param_unit, -param_unit}, {0, param_unit, -param_unit}, {0, param_unit, -param_unit},
    };
    memcpy(&cmd_buff[2], &param, sizeof(param));

    LOG_WARNING(Service_HID, "(STUBBED) called");
}

void GetSoundVolume(Service::Interface* self) {
    u32* cmd_buff = Kernel::GetCommandBuffer();

    const u8 volume = 0x3F; // TODO(purpasmart): Find out if this is the max value for the volume

    cmd_buff[1] = RESULT_SUCCESS.raw;
    cmd_buff[2] = volume;

    LOG_WARNING(Service_HID, "(STUBBED) called");
}

void Init() {
    using namespace Kernel;

    AddService(new HID_U_Interface);
    AddService(new HID_SPVR_Interface);

    is_device_reload_pending.store(true);

    using Kernel::MemoryPermission;
    shared_mem =
        SharedMemory::Create(nullptr, 0x1000, MemoryPermission::ReadWrite, MemoryPermission::Read,
                             0, Kernel::MemoryRegion::BASE, "HID:SharedMemory");

    next_pad_index = 0;
    next_touch_index = 0;
    next_accelerometer_index = 0;
    next_gyroscope_index = 0;

    enable_accelerometer_count = 0;
    enable_gyroscope_count = 0;

    // Create event handles
    event_pad_or_touch_1 = Event::Create(ResetType::OneShot, "HID:EventPadOrTouch1");
    event_pad_or_touch_2 = Event::Create(ResetType::OneShot, "HID:EventPadOrTouch2");
    event_accelerometer = Event::Create(ResetType::OneShot, "HID:EventAccelerometer");
    event_gyroscope = Event::Create(ResetType::OneShot, "HID:EventGyroscope");
    event_debug_pad = Event::Create(ResetType::OneShot, "HID:EventDebugPad");

    // Register update callbacks
    pad_update_event = CoreTiming::RegisterEvent("HID::UpdatePadCallback", UpdatePadCallback);
    accelerometer_update_event =
        CoreTiming::RegisterEvent("HID::UpdateAccelerometerCallback", UpdateAccelerometerCallback);
    gyroscope_update_event =
        CoreTiming::RegisterEvent("HID::UpdateGyroscopeCallback", UpdateGyroscopeCallback);

    CoreTiming::ScheduleEvent(pad_update_ticks, pad_update_event);
}

void Shutdown() {
    shared_mem = nullptr;
    event_pad_or_touch_1 = nullptr;
    event_pad_or_touch_2 = nullptr;
    event_accelerometer = nullptr;
    event_gyroscope = nullptr;
    event_debug_pad = nullptr;
    UnloadInputDevices();
}

void ReloadInputDevices() {
    is_device_reload_pending.store(true);
}

} // namespace HID
示例#18
0
        void locate_controls()
        {
            m_base.set_client_dimension(dimension_type{ width_type{ 36 }, height_type{ 10 } });

            m_p_application_image->fit_to_content();
            m_p_application_image->set_position(position_type{ left_type{ 2 }, top_type{ 1 } });
            
            const auto label_left =
                left_type{ 2 } +
                tetengo2::gui::dimension<dimension_type>::width(m_p_application_image->dimension()) +
                left_type{ 1 };

            m_p_title_label->fit_to_content();
            m_p_title_label->set_position(position_type{ label_left, top_type{ 1 } });

            m_p_copyright_label->fit_to_content();
            m_p_copyright_label->set_position(position_type{ label_left, top_type{ 3 } });

            m_p_link_label->fit_to_content();
            m_p_link_label->set_position(position_type{ label_left, top_type{ 5 } });

            m_p_ok_button->set_dimension(dimension_type{ width_type{ 8 }, height_type{ 2 } });
            m_p_ok_button->set_position(position_type{ left_type{ 26 }, top_type{ 7 } });
        }
示例#19
0
int ReadLiveStream(unsigned char *pBuffer, unsigned int iBufferSize)
{
  int ret = g_pvr_client->read_data(pBuffer, iBufferSize);
  return ret;
}
示例#20
0
void MetadataManager::refreshActiveMetadata(std::unique_ptr<CollectionMetadata> remoteMetadata) {
    LOG(1) << "Refreshing the active metadata from "
           << (_activeMetadataTracker->metadata ? _activeMetadataTracker->metadata->toStringBasic()
                                                : "(empty)")
           << ", to " << (remoteMetadata ? remoteMetadata->toStringBasic() : "(empty)");

    stdx::lock_guard<stdx::mutex> scopedLock(_managerLock);

    // Collection is not sharded anymore
    if (!remoteMetadata) {
        log() << "Marking collection as not sharded.";

        _receivingChunks.clear();
        _rangesToClean.clear();

        _setActiveMetadata_inlock(nullptr);
        return;
    }

    invariant(!remoteMetadata->getCollVersion().isWriteCompatibleWith(ChunkVersion::UNSHARDED()));
    invariant(!remoteMetadata->getShardVersion().isWriteCompatibleWith(ChunkVersion::UNSHARDED()));

    // Collection is not sharded currently
    if (!_activeMetadataTracker->metadata) {
        log() << "Marking collection as sharded with " << remoteMetadata->toStringBasic();

        invariant(_receivingChunks.empty());
        invariant(_rangesToClean.empty());

        _setActiveMetadata_inlock(std::move(remoteMetadata));
        return;
    }

    // If the metadata being installed has a different epoch from ours, this means the collection
    // was dropped and recreated, so we must entirely reset the metadata state
    if (_activeMetadataTracker->metadata->getCollVersion().epoch() !=
        remoteMetadata->getCollVersion().epoch()) {
        log() << "Overwriting collection metadata due to epoch change.";

        _receivingChunks.clear();
        _rangesToClean.clear();

        _setActiveMetadata_inlock(std::move(remoteMetadata));
        return;
    }

    // We already have newer version
    if (_activeMetadataTracker->metadata->getCollVersion() >= remoteMetadata->getCollVersion()) {
        LOG(1) << "Attempted to refresh active metadata "
               << _activeMetadataTracker->metadata->toStringBasic() << " with an older "
               << remoteMetadata->toStringBasic();

        return;
    }

    // Resolve any receiving chunks, which might have completed by now
    for (auto it = _receivingChunks.begin(); it != _receivingChunks.end();) {
        const BSONObj min = it->first;
        const BSONObj max = it->second;

        // Our pending range overlaps at least one chunk
        if (rangeMapContains(remoteMetadata->getChunks(), min, max)) {
            // The remote metadata contains a chunk we were earlier in the process of receiving, so
            // we deem it successfully received.
            LOG(2) << "Verified chunk " << ChunkRange(min, max).toString()
                   << " was migrated earlier to this shard";

            _receivingChunks.erase(it++);
            continue;
        } else if (!rangeMapOverlaps(remoteMetadata->getChunks(), min, max)) {
            ++it;
            continue;
        }

        // Partial overlap indicates that the earlier migration has failed, but the chunk being
        // migrated underwent some splits and other migrations and ended up here again. In this
        // case, we will request full reload of the metadata. Currently this cannot happen, because
        // all migrations are with the explicit knowledge of the recipient shard. However, we leave
        // the option open so that chunk splits can do empty chunk move without having to notify the
        // recipient.
        RangeVector overlappedChunks;
        getRangeMapOverlap(remoteMetadata->getChunks(), min, max, &overlappedChunks);

        for (const auto& overlapChunkMin : overlappedChunks) {
            auto itRecv = _receivingChunks.find(overlapChunkMin.first);
            invariant(itRecv != _receivingChunks.end());

            const ChunkRange receivingRange(itRecv->first, itRecv->second);

            _receivingChunks.erase(itRecv);

            // Make sure any potentially partially copied chunks are scheduled to be cleaned up
            _addRangeToClean_inlock(receivingRange);
        }

        // Need to reset the iterator
        it = _receivingChunks.begin();
    }

    // For compatibility with the current range deleter, which is driven entirely by the contents of
    // the CollectionMetadata update the pending chunks
    for (const auto& receivingChunk : _receivingChunks) {
        ChunkType chunk;
        chunk.setMin(receivingChunk.first);
        chunk.setMax(receivingChunk.second);
        remoteMetadata = remoteMetadata->clonePlusPending(chunk);
    }

    _setActiveMetadata_inlock(std::move(remoteMetadata));
}
示例#21
0
bool IsTimeshifting(void)
{
  return g_pvr_client->is_timeshifting();
}
示例#22
0
void Stage::process(void)
{
  static ProcessingState last_processing_state = ProcessingState::Idle;
  static std::unique_ptr<StageBuilder> builder;
  bool done = false;

  // Have we changed states?
  if (impl->processing_state_ != last_processing_state)
  {
    // Clean up the last state if needed.
    switch (last_processing_state)
    {
    case ProcessingState::SmoothTerrain:
      impl->UpdateAllColumnData();
      break;

    default:
      break;
    }

    // Update the last processing state.
    last_processing_state = impl->processing_state_;

    // Initialize the new state if needed.
    switch (impl->processing_state_)
    {
    case ProcessingState::GenerateTerrain:
      builder.reset(
        new StageBuilderTerrain(*this, impl->seed_,
                                Settings::terrainStageHeight,
                                Settings::terrainFeatureHeight,
                                Settings::terrainFrequency,
                                Settings::terrainOctaveCount,
                                Settings::terrainPersistence,
                                Settings::terrainLacunarity));
      break;

    case ProcessingState::AddDeposits:
      builder.reset(new StageBuilderDeposits(*this, impl->seed_));
      break;

    case ProcessingState::AddLakes:
      builder.reset(
        new StageBuilderLakes(*this, impl->seed_,
                              Settings::terrainSeaLevel));
      break;

    case ProcessingState::AddBeaches:
      builder.reset(
        new StageBuilderBeaches(*this, impl->seed_,
                                Settings::terrainSeaLevel));
      break;

    case ProcessingState::AddRivers:
      builder.reset(
        new StageBuilderRivers(*this, impl->seed_,
                               Settings::terrainSeaLevel));
      break;

    case ProcessingState::AddFlora:
      builder.reset(
        new StageBuilderFlora(*this, impl->seed_,
                              Settings::terrainPlainsThreshold,
                              Settings::terrainForestThreshold));
      break;

    case ProcessingState::AddFauna:
      // TODO: create builder for this!
      builder.reset();
      break;

    case ProcessingState::SetPlayerKnowledge:
      builder.reset(new StageBuilderKnownStatus(*this, impl->seed_));
      break;

    default:
      builder.reset();
      break;
    }
  }

  if (builder.get() != nullptr)
  {
    done = builder->Build();
  }
  else
  {
    done = true;
  }

  // Other stuff to do while in the state.
  switch (impl->processing_state_)
  {
  case ProcessingState::Idle:
    // This is the state prior to world generation.
    break;

  case ProcessingState::GenerateTerrain:
    if (done)
    {
      impl->processing_state_ = ProcessingState::AddDeposits;
    }
    break;

  case ProcessingState::AddDeposits:
    if (done)
    {
      impl->UpdateAllColumnData();
      impl->processing_state_ = ProcessingState::AddLakes;
    }
    break;

  case ProcessingState::AddLakes:
    if (done)
    {
      impl->processing_state_ = ProcessingState::AddBeaches;
    }
    break;

  case ProcessingState::AddBeaches:
    if (done)
    {
      impl->processing_state_ = ProcessingState::AddRivers;
    }
    break;

  case ProcessingState::AddRivers:
    if (done)
    {
      impl->UpdateAllColumnData();
      impl->processing_state_ = ProcessingState::AddFlora;
    }
    break;

  case ProcessingState::AddFlora:
    if (done)
    {
      impl->processing_state_ = ProcessingState::AddFauna;
    }
    break;

  case ProcessingState::AddFauna:
    impl->processing_state_ = ProcessingState::SetPlayerKnowledge;
    break;

  case ProcessingState::SetPlayerKnowledge:
    if (done)
    {
      std::cout << "Terrain generation complete.  Moving to PAUSED state."
                << std::endl;

      // At this point it's okay to do map rendering.
      impl->okay_to_render_map_ = true;

      impl->processing_state_ = ProcessingState::Paused;
    }
    break;

  case ProcessingState::Paused:
    // This is the state when world processing is paused.
    break;

  case ProcessingState::Running:
    // This is the state when world processing is running.
    impl->UpdateAllColumnData();
    break;

  case ProcessingState::Halted:
    // This is the state when world processing is halted.
    break;

  default:
    break;
  }
}
示例#23
0
void ADDON_Destroy()
{
  g_pvr_client.reset();
  m_bCreated = false;
  m_CurStatus = ADDON_STATUS_UNKNOWN;
}
示例#24
0
void CGUIEPGGridContainerModel::Refresh(const std::unique_ptr<CFileItemList> &items, const CDateTime &gridStart, const CDateTime &gridEnd, int iRulerUnit, int iBlocksPerPage, float fBlockSize)
{
  Reset();

  ////////////////////////////////////////////////////////////////////////
  // Create programme & channel items
  m_programmeItems.reserve(items->Size());
  CFileItemPtr fileItem;
  int iLastChannelID = -1;
  ItemsPtr itemsPointer;
  itemsPointer.start = 0;
  CPVRChannelPtr channel;
  int j = 0;
  for (int i = 0; i < items->Size(); ++i)
  {
    fileItem = items->Get(i);
    if (!fileItem->HasEPGInfoTag() || !fileItem->GetEPGInfoTag()->HasChannel())
      continue;

    m_programmeItems.emplace_back(fileItem);

    channel = fileItem->GetEPGInfoTag()->Channel();
    if (!channel)
      continue;

    int iCurrentChannelID = channel->ChannelID();
    if (iCurrentChannelID != iLastChannelID)
    {
      if (j > 0)
      {
        itemsPointer.stop = j - 1;
        m_epgItemsPtr.emplace_back(itemsPointer);
        itemsPointer.start = j;
      }
      iLastChannelID = iCurrentChannelID;
      m_channelItems.emplace_back(CFileItemPtr(new CFileItem(channel)));
    }
    ++j;
  }
  if (!m_programmeItems.empty())
  {
    itemsPointer.stop = m_programmeItems.size() - 1;
    m_epgItemsPtr.emplace_back(itemsPointer);
  }

  /* check for invalid start and end time */
  if (gridStart >= gridEnd)
  {
    // default to start "now minus GRID_START_PADDING minutes" and end "start plus one page".
    m_gridStart = CDateTime::GetUTCDateTime() - CDateTimeSpan(0, 0, GetGridStartPadding(), 0);
    m_gridEnd = m_gridStart + CDateTimeSpan(0, 0, iBlocksPerPage * MINSPERBLOCK, 0);
  }
  else if (gridStart > (CDateTime::GetUTCDateTime() - CDateTimeSpan(0, 0, GetGridStartPadding(), 0)))
  {
    // adjust to start "now minus GRID_START_PADDING minutes".
    m_gridStart = CDateTime::GetUTCDateTime() - CDateTimeSpan(0, 0, GetGridStartPadding(), 0);
    m_gridEnd = gridEnd;
  }
  else
  {
    m_gridStart = gridStart;
    m_gridEnd = gridEnd;
  }

  // roundup
  m_gridStart = CDateTime(m_gridStart.GetYear(), m_gridStart.GetMonth(), m_gridStart.GetDay(), m_gridStart.GetHour(), m_gridStart.GetMinute() >= 30 ? 30 : 0, 0);
  m_gridEnd = CDateTime(m_gridEnd.GetYear(), m_gridEnd.GetMonth(), m_gridEnd.GetDay(), m_gridEnd.GetHour(), m_gridEnd.GetMinute() >= 30 ? 30 : 0, 0);

  ////////////////////////////////////////////////////////////////////////
  // Create ruler items
  CDateTime ruler;
  ruler.SetFromUTCDateTime(m_gridStart);
  CDateTime rulerEnd;
  rulerEnd.SetFromUTCDateTime(m_gridEnd);
  CFileItemPtr rulerItem(new CFileItem(ruler.GetAsLocalizedDate(true)));
  rulerItem->SetProperty("DateLabel", true);
  m_rulerItems.emplace_back(rulerItem);

  const CDateTimeSpan unit(0, 0, iRulerUnit * MINSPERBLOCK, 0);
  for (; ruler < rulerEnd; ruler += unit)
  {
    rulerItem.reset(new CFileItem(ruler.GetAsLocalizedTime("", false)));
    rulerItem->SetLabel2(ruler.GetAsLocalizedDate(true));
    m_rulerItems.emplace_back(rulerItem);
  }

  FreeItemsMemory();

  ////////////////////////////////////////////////////////////////////////
  // Create epg grid
  const CDateTimeSpan blockDuration(0, 0, MINSPERBLOCK, 0);
  const CDateTimeSpan gridDuration(m_gridEnd - m_gridStart);
  m_blocks = (gridDuration.GetDays() * 24 * 60 + gridDuration.GetHours() * 60 + gridDuration.GetMinutes()) / MINSPERBLOCK;
  if (m_blocks >= MAXBLOCKS)
    m_blocks = MAXBLOCKS;
  else if (m_blocks < iBlocksPerPage)
    m_blocks = iBlocksPerPage;

  m_gridIndex.reserve(m_channelItems.size());
  const std::vector<GridItem> blocks(m_blocks);

  for (size_t channel = 0; channel < m_channelItems.size(); ++channel)
  {
    m_gridIndex.emplace_back(blocks);

    CDateTime gridCursor(m_gridStart); //reset cursor for new channel
    unsigned long progIdx = m_epgItemsPtr[channel].start;
    unsigned long lastIdx = m_epgItemsPtr[channel].stop;
    int iEpgId            = m_programmeItems[progIdx]->GetEPGInfoTag()->EpgID();
    int itemSize          = 1; // size of the programme in blocks
    int savedBlock        = 0;
    CFileItemPtr item;
    CPVREpgInfoTagPtr tag;

    for (int block = 0; block < m_blocks; ++block)
    {
      while (progIdx <= lastIdx)
      {
        item = m_programmeItems[progIdx];
        tag = item->GetEPGInfoTag();

        // Note: Start block of an event is start-time-based calculated block + 1,
        //       unless start times matches exactly the begin of a block.

        if (tag->EpgID() != iEpgId || gridCursor < tag->StartAsUTC() || m_gridEnd <= tag->StartAsUTC())
          break;

        if (gridCursor < tag->EndAsUTC())
        {
          m_gridIndex[channel][block].item = item;
          m_gridIndex[channel][block].progIndex = progIdx;
          break;
        }

        progIdx++;
      }

      gridCursor += blockDuration;

      if (block == 0)
        continue;

      const CFileItemPtr prevItem(m_gridIndex[channel][block - 1].item);
      const CFileItemPtr currItem(m_gridIndex[channel][block].item);

      if (block == m_blocks - 1 || prevItem != currItem)
      {
        // special handling for last block.
        int blockDelta = -1;
        int sizeDelta = 0;
        if (block == m_blocks - 1 && prevItem == currItem)
        {
          itemSize++;
          blockDelta = 0;
          sizeDelta = 1;
        }

        if (prevItem)
        {
          m_gridIndex[channel][savedBlock].item->SetProperty("GenreType", prevItem->GetEPGInfoTag()->GenreType());
        }
        else
        {
          CPVREpgInfoTagPtr gapTag(CPVREpgInfoTag::CreateDefaultTag());
          gapTag->SetChannel(m_channelItems[channel]->GetPVRChannelInfoTag());
          CFileItemPtr gapItem(new CFileItem(gapTag));
          for (int i = block + blockDelta; i >= block - itemSize + sizeDelta; --i)
          {
            m_gridIndex[channel][i].item = gapItem;
          }
        }

        float fItemWidth = itemSize * fBlockSize;
        m_gridIndex[channel][savedBlock].originWidth = fItemWidth;
        m_gridIndex[channel][savedBlock].width = fItemWidth;

        itemSize = 1;
        savedBlock = block;

        // special handling for last block.
        if (block == m_blocks - 1 && prevItem != currItem)
        {
          if (currItem)
          {
            m_gridIndex[channel][savedBlock].item->SetProperty("GenreType", currItem->GetEPGInfoTag()->GenreType());
          }
          else
          {
            CPVREpgInfoTagPtr gapTag(CPVREpgInfoTag::CreateDefaultTag());
            gapTag->SetChannel(m_channelItems[channel]->GetPVRChannelInfoTag());
            CFileItemPtr gapItem(new CFileItem(gapTag));
            m_gridIndex[channel][block].item = gapItem;
          }

          m_gridIndex[channel][savedBlock].originWidth = fBlockSize; // size always 1 block here
          m_gridIndex[channel][savedBlock].width = fBlockSize;
        }
      }
      else
      {
        itemSize++;
      }
    }
  }
}
示例#25
0
文件: ieqpro.cpp 项目: mp77/indi
void ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int num)
{
        scope->ISNewSwitch(dev, name, states, names, num);
}
示例#26
0
bool SetFontByName(const char* name, size_t size)
{
	g_fontptr.reset(new FontManager(name, size));
	return true;
}
示例#27
0
文件: ieqpro.cpp 项目: mp77/indi
void ISNewNumber(const char *dev, const char *name, double values[], char *names[], int num)
{
        scope->ISNewNumber(dev, name, values, names, num);
}
示例#28
0
Diagnostics* Diagnostics::Get()
{
    static std::unique_ptr<Diagnostics> singleton = make_unique<Diagnostics>();
    return singleton.get();
}
示例#29
0
void Enum::appendChild(std::unique_ptr<ConstantAssignment> value)
{
	setAsParent(value.get());
	m_children.push_back(std::move(value));
}
示例#30
0
 NcclCommList(const std::vector<int>& devices)
   : comms(new ncclComm_t[devices.size()]), ndevices(devices.size()) {
   CHECK(ncclCommInitAll(comms.get(), devices.size(), devices.data()));
 }