<commit_before>/*
 * Copyright (C) 2008 Google, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "Gradient.h"

#include "CSSParser.h"
#include "GraphicsContext.h"

#include "SkGradientShader.h"
#include "SkiaUtils.h"

namespace WebCore {

void Gradient::platformDestroy()
{
    if (m_gradient)
        m_gradient->safeUnref();
    m_gradient = 0;
}

static inline U8CPU F2B(float x)
{
    return static_cast<int>(x * 255);
}

static SkColor makeSkColor(float a, float r, float g, float b)
{
    return SkColorSetARGB(F2B(a), F2B(r), F2B(g), F2B(b));
}

// Determine the total number of stops needed, including pseudo-stops at the
// ends as necessary.
static size_t total_stops_needed(const Gradient::ColorStop* stopData, size_t count)
{
    const Gradient::ColorStop* stop = stopData;
    size_t count_used = count;
    if (count < 1 || stop->stop > 0.0)
      count_used++;
    stop += count - 1;
    if (count < 2 || stop->stop < 1.0)
      count_used++;
    return count_used;
}

// Collect sorted stop position and color information into the pos and colors
// buffers, ensuring stops at both 0.0 and 1.0.  The buffers must be large
// enough to hold information for all stops, including the new endpoints if
// stops at 0.0 and 1.0 aren't already included.
static void fill_stops(const Gradient::ColorStop* stopData,
                       size_t count, SkScalar* pos, SkColor* colors)
{
    const Gradient::ColorStop* stop = stopData;
    size_t start = 0;
    if (count < 1) {
        // A gradient with no stops must be transparent black.
        pos[0] = WebCoreFloatToSkScalar(0.0);
        colors[0] = makeSkColor(0.0, 0.0, 0.0, 0.0);
        start = 1;
    } else if (stop->stop > 0.0) {
        // Copy the first stop to 0.0. The first stop position may have a slight
        // rounding error, but we don't care in this float comparison, since
        // 0.0 comes through cleanly and people aren't likely to want a gradient
        // with a stop at (0 + epsilon).
        pos[0] = WebCoreFloatToSkScalar(0.0);
        colors[0] = makeSkColor(stop->alpha, stop->red, stop->green, stop->blue);
        start = 1;
    }

    for (size_t i = start; i < start + count; i++) {
        pos[i] = WebCoreFloatToSkScalar(stop->stop);
        colors[i] = makeSkColor(stop->alpha, stop->red, stop->green, stop->blue);
        ++stop;
    }

    // Copy the last stop to 1.0 if needed.  See comment above about this float
    // comparison.
    if (count < 1 || (--stop)->stop < 1.0) {
        pos[start + count] = WebCoreFloatToSkScalar(1.0);
        colors[start + count] = colors[start + count - 1];
    }
}

SkShader* Gradient::platformGradient()
{
    if (m_gradient)
        return m_gradient;

    size_t count_used = total_stops_needed(m_stops.data(), m_stops.size());
    ASSERT(count_used >= 2);
    ASSERT(count_used >= m_stops.size());

    // FIXME: Why is all this manual pointer math needed?!
    SkAutoMalloc storage(count_used * (sizeof(SkColor) + sizeof(SkScalar)));
    SkColor* colors = (SkColor*)storage.get();
    SkScalar* pos = (SkScalar*)(colors + count_used);

    fill_stops(m_stops.data(), m_stops.size(), pos, colors);

    if (m_radial) {
        // TODO(mmoss) CSS radial Gradients allow an offset focal point (the
        // "start circle"), but skia doesn't seem to support that, so this just
        // ignores m_p0/m_r0 and draws the gradient centered in the "end
        // circle" (m_p1/m_r1).
        // See http://webkit.org/blog/175/introducing-css-gradients/ for a
        // description of the expected behavior.
        m_gradient = SkGradientShader::CreateRadial(m_p1,
            WebCoreFloatToSkScalar(m_r1), colors, pos,
            static_cast<int>(count_used), SkShader::kClamp_TileMode);
    } else {
        SkPoint pts[2] = { m_p0, m_p1 };
        m_gradient = SkGradientShader::CreateLinear(pts, colors, pos,
            static_cast<int>(count_used), SkShader::kClamp_TileMode);
    }

    return m_gradient;
}

void Gradient::fill(GraphicsContext* context, const FloatRect& rect)
{
    context->setFillGradient(this);
    context->fillRect(rect);
}

} // namespace WebCore
<commit_msg>Sort gradient stops before processing.<commit_after>/*
 * Copyright (C) 2008 Google, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "Gradient.h"

#include "CSSParser.h"
#include "GraphicsContext.h"

#include "SkGradientShader.h"
#include "SkiaUtils.h"

namespace WebCore {

void Gradient::platformDestroy()
{
    if (m_gradient)
        m_gradient->safeUnref();
    m_gradient = 0;
}

static inline U8CPU F2B(float x)
{
    return static_cast<int>(x * 255);
}

static SkColor makeSkColor(float a, float r, float g, float b)
{
    return SkColorSetARGB(F2B(a), F2B(r), F2B(g), F2B(b));
}

// Determine the total number of stops needed, including pseudo-stops at the
// ends as necessary.
static size_t total_stops_needed(const Gradient::ColorStop* stopData, size_t count)
{
    const Gradient::ColorStop* stop = stopData;
    size_t count_used = count;
    if (count < 1 || stop->stop > 0.0)
      count_used++;
    stop += count - 1;
    if (count < 2 || stop->stop < 1.0)
      count_used++;
    return count_used;
}

// Collect sorted stop position and color information into the pos and colors
// buffers, ensuring stops at both 0.0 and 1.0.  The buffers must be large
// enough to hold information for all stops, including the new endpoints if
// stops at 0.0 and 1.0 aren't already included.
static void fill_stops(const Gradient::ColorStop* stopData,
                       size_t count, SkScalar* pos, SkColor* colors)
{
    const Gradient::ColorStop* stop = stopData;
    size_t start = 0;
    if (count < 1) {
        // A gradient with no stops must be transparent black.
        pos[0] = WebCoreFloatToSkScalar(0.0);
        colors[0] = makeSkColor(0.0, 0.0, 0.0, 0.0);
        start = 1;
    } else if (stop->stop > 0.0) {
        // Copy the first stop to 0.0. The first stop position may have a slight
        // rounding error, but we don't care in this float comparison, since
        // 0.0 comes through cleanly and people aren't likely to want a gradient
        // with a stop at (0 + epsilon).
        pos[0] = WebCoreFloatToSkScalar(0.0);
        colors[0] = makeSkColor(stop->alpha, stop->red, stop->green, stop->blue);
        start = 1;
    }

    for (size_t i = start; i < start + count; i++) {
        pos[i] = WebCoreFloatToSkScalar(stop->stop);
        colors[i] = makeSkColor(stop->alpha, stop->red, stop->green, stop->blue);
        ++stop;
    }

    // Copy the last stop to 1.0 if needed.  See comment above about this float
    // comparison.
    if (count < 1 || (--stop)->stop < 1.0) {
        pos[start + count] = WebCoreFloatToSkScalar(1.0);
        colors[start + count] = colors[start + count - 1];
    }
}

static inline bool compareStops(const Gradient::ColorStop& a, const Gradient::ColorStop& b)
{
    return a.stop < b.stop;
}

SkShader* Gradient::platformGradient()
{
    if (m_gradient)
        return m_gradient;

    size_t count_used = total_stops_needed(m_stops.data(), m_stops.size());
    ASSERT(count_used >= 2);
    ASSERT(count_used >= m_stops.size());

    // FIXME: Why is all this manual pointer math needed?!
    SkAutoMalloc storage(count_used * (sizeof(SkColor) + sizeof(SkScalar)));
    SkColor* colors = (SkColor*)storage.get();
    SkScalar* pos = (SkScalar*)(colors + count_used);

    // TODO: This and compareStops() are also in Gradient.cpp and
    // CSSGradientValue.cpp; probably should refactor in WebKit.
    if (!m_stopsSorted) {
        if (m_stops.size())
            std::stable_sort(m_stops.begin(), m_stops.end(), compareStops);
        m_stopsSorted = true;
    }
    fill_stops(m_stops.data(), m_stops.size(), pos, colors);

    if (m_radial) {
        // TODO(mmoss) CSS radial Gradients allow an offset focal point (the
        // "start circle"), but skia doesn't seem to support that, so this just
        // ignores m_p0/m_r0 and draws the gradient centered in the "end
        // circle" (m_p1/m_r1).
        // See http://webkit.org/blog/175/introducing-css-gradients/ for a
        // description of the expected behavior.
        m_gradient = SkGradientShader::CreateRadial(m_p1,
            WebCoreFloatToSkScalar(m_r1), colors, pos,
            static_cast<int>(count_used), SkShader::kClamp_TileMode);
    } else {
        SkPoint pts[2] = { m_p0, m_p1 };
        m_gradient = SkGradientShader::CreateLinear(pts, colors, pos,
            static_cast<int>(count_used), SkShader::kClamp_TileMode);
    }

    return m_gradient;
}

void Gradient::fill(GraphicsContext* context, const FloatRect& rect)
{
    context->setFillGradient(this);
    context->fillRect(rect);
}

} // namespace WebCore
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/modules/video_coding/main/source/receiver.h"

#include <assert.h>

#include "webrtc/modules/video_coding/main/source/encoded_frame.h"
#include "webrtc/modules/video_coding/main/source/internal_defines.h"
#include "webrtc/modules/video_coding/main/source/media_opt_util.h"
#include "webrtc/system_wrappers/interface/clock.h"
#include "webrtc/system_wrappers/interface/trace.h"
#include "webrtc/system_wrappers/interface/trace_event.h"

namespace webrtc {

enum { kMaxReceiverDelayMs = 10000 };

VCMReceiver::VCMReceiver(VCMTiming* timing,
                         Clock* clock,
                         EventFactory* event_factory,
                         int32_t vcm_id,
                         int32_t receiver_id,
                         bool master)
    : crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
      vcm_id_(vcm_id),
      clock_(clock),
      receiver_id_(receiver_id),
      master_(master),
      jitter_buffer_(clock_, event_factory, vcm_id, receiver_id, master),
      timing_(timing),
      render_wait_event_(event_factory->CreateEvent()),
      state_(kPassive),
      max_video_delay_ms_(kMaxVideoDelayMs) {}

VCMReceiver::~VCMReceiver() {
  render_wait_event_->Set();
  delete crit_sect_;
}

void VCMReceiver::Reset() {
  CriticalSectionScoped cs(crit_sect_);
  if (!jitter_buffer_.Running()) {
    jitter_buffer_.Start();
  } else {
    jitter_buffer_.Flush();
  }
  render_wait_event_->Reset();
  if (master_) {
    state_ = kReceiving;
  } else {
    state_ = kPassive;
  }
}

int32_t VCMReceiver::Initialize() {
  CriticalSectionScoped cs(crit_sect_);
  Reset();
  if (!master_) {
    SetNackMode(kNoNack, -1, -1);
  }
  return VCM_OK;
}

void VCMReceiver::UpdateRtt(uint32_t rtt) {
  jitter_buffer_.UpdateRtt(rtt);
}

int32_t VCMReceiver::InsertPacket(const VCMPacket& packet,
                                  uint16_t frame_width,
                                  uint16_t frame_height) {
  if (packet.frameType == kVideoFrameKey) {
    WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCoding,
                 VCMId(vcm_id_, receiver_id_),
                 "Inserting key frame packet seqnum=%u, timestamp=%u",
                 packet.seqNum, packet.timestamp);
  }

  // Insert the packet into the jitter buffer. The packet can either be empty or
  // contain media at this point.
  bool retransmitted = false;
  const VCMFrameBufferEnum ret = jitter_buffer_.InsertPacket(packet,
                                                             &retransmitted);
  if (ret == kOldPacket) {
    return VCM_OK;
  } else if (ret == kFlushIndicator) {
    return VCM_FLUSH_INDICATOR;
  } else if (ret < 0) {
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCoding,
                 VCMId(vcm_id_, receiver_id_),
                 "Error inserting packet seqnum=%u, timestamp=%u",
                 packet.seqNum, packet.timestamp);
    return VCM_JITTER_BUFFER_ERROR;
  }
  if (ret == kCompleteSession && !retransmitted) {
    // We don't want to include timestamps which have suffered from
    // retransmission here, since we compensate with extra retransmission
    // delay within the jitter estimate.
    timing_->IncomingTimestamp(packet.timestamp, clock_->TimeInMilliseconds());
  }
  if (master_) {
    // Only trace the primary receiver to make it possible to parse and plot
    // the trace file.
    WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding,
                 VCMId(vcm_id_, receiver_id_),
                 "Packet seqnum=%u timestamp=%u inserted at %u",
                 packet.seqNum, packet.timestamp,
                 MaskWord64ToUWord32(clock_->TimeInMilliseconds()));
  }
  return VCM_OK;
}

VCMEncodedFrame* VCMReceiver::FrameForDecoding(
    uint16_t max_wait_time_ms,
    int64_t& next_render_time_ms,
    bool render_timing,
    VCMReceiver* dual_receiver) {
  const int64_t start_time_ms = clock_->TimeInMilliseconds();
  uint32_t frame_timestamp = 0;
  // Exhaust wait time to get a complete frame for decoding.
  bool found_frame = jitter_buffer_.NextCompleteTimestamp(
      max_wait_time_ms, &frame_timestamp);

  if (!found_frame) {
    // Get an incomplete frame when enabled.
    const bool dual_receiver_enabled_and_passive = (dual_receiver != NULL &&
        dual_receiver->State() == kPassive &&
        dual_receiver->NackMode() == kNack);
    if (dual_receiver_enabled_and_passive &&
        !jitter_buffer_.CompleteSequenceWithNextFrame()) {
      // Jitter buffer state might get corrupt with this frame.
      dual_receiver->CopyJitterBufferStateFromReceiver(*this);
    }
    found_frame = jitter_buffer_.NextMaybeIncompleteTimestamp(
        &frame_timestamp);
  }

  if (!found_frame) {
    return NULL;
  }

  // We have a frame - Set timing and render timestamp.
  timing_->SetJitterDelay(jitter_buffer_.EstimatedJitterMs());
  const int64_t now_ms = clock_->TimeInMilliseconds();
  timing_->UpdateCurrentDelay(frame_timestamp);
  next_render_time_ms = timing_->RenderTimeMs(frame_timestamp, now_ms);
  // Check render timing.
  bool timing_error = false;
  // Assume that render timing errors are due to changes in the video stream.
  if (next_render_time_ms < 0) {
    timing_error = true;
  } else if (abs(next_render_time_ms - now_ms) > max_video_delay_ms_) {
    WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCoding,
                 VCMId(vcm_id_, receiver_id_),
                 "This frame is out of our delay bounds, resetting jitter "
                 "buffer: %d > %d",
                 static_cast<int>(abs(next_render_time_ms - now_ms)),
                 max_video_delay_ms_);
    timing_error = true;
  } else if (static_cast<int>(timing_->TargetVideoDelay()) >
             max_video_delay_ms_) {
    WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCoding,
                 VCMId(vcm_id_, receiver_id_),
                 "More than %u ms target delay. Flushing jitter buffer and"
                 "resetting timing.", max_video_delay_ms_);
    timing_error = true;
  }

  if (timing_error) {
    // Timing error => reset timing and flush the jitter buffer.
    jitter_buffer_.Flush();
    timing_->Reset();
    return NULL;
  }

  if (!render_timing) {
    // Decode frame as close as possible to the render timestamp.
    const int32_t available_wait_time = max_wait_time_ms -
        static_cast<int32_t>(clock_->TimeInMilliseconds() - start_time_ms);
    uint16_t new_max_wait_time = static_cast<uint16_t>(
        VCM_MAX(available_wait_time, 0));
    uint32_t wait_time_ms = timing_->MaxWaitingTime(
        next_render_time_ms, clock_->TimeInMilliseconds());
    if (new_max_wait_time < wait_time_ms) {
      // We're not allowed to wait until the frame is supposed to be rendered,
      // waiting as long as we're allowed to avoid busy looping, and then return
      // NULL. Next call to this function might return the frame.
      render_wait_event_->Wait(max_wait_time_ms);
      return NULL;
    }
    // Wait until it's time to render.
    render_wait_event_->Wait(wait_time_ms);
  }

  // Extract the frame from the jitter buffer and set the render time.
  VCMEncodedFrame* frame = jitter_buffer_.ExtractAndSetDecode(frame_timestamp);
  if (frame == NULL) {
    return NULL;
  }
  frame->SetRenderTime(next_render_time_ms);
  TRACE_EVENT_ASYNC_STEP1("webrtc", "Video", frame->TimeStamp(),
                          "SetRenderTS", "render_time", next_render_time_ms);
  if (dual_receiver != NULL) {
    dual_receiver->UpdateState(*frame);
  }
  if (!frame->Complete()) {
    // Update stats for incomplete frames.
    bool retransmitted = false;
    const int64_t last_packet_time_ms =
        jitter_buffer_.LastPacketTime(frame, &retransmitted);
    if (last_packet_time_ms >= 0 && !retransmitted) {
      // We don't want to include timestamps which have suffered from
      // retransmission here, since we compensate with extra retransmission
      // delay within the jitter estimate.
      timing_->IncomingTimestamp(frame_timestamp, last_packet_time_ms);
    }
  }
  return frame;
}

void VCMReceiver::ReleaseFrame(VCMEncodedFrame* frame) {
  jitter_buffer_.ReleaseFrame(frame);
}

void VCMReceiver::ReceiveStatistics(uint32_t* bitrate,
                                    uint32_t* framerate) {
  assert(bitrate);
  assert(framerate);
  jitter_buffer_.IncomingRateStatistics(framerate, bitrate);
}

void VCMReceiver::ReceivedFrameCount(VCMFrameCount* frame_count) const {
  assert(frame_count);
  jitter_buffer_.FrameStatistics(&frame_count->numDeltaFrames,
                                 &frame_count->numKeyFrames);
}

uint32_t VCMReceiver::DiscardedPackets() const {
  return jitter_buffer_.num_discarded_packets();
}

void VCMReceiver::SetNackMode(VCMNackMode nackMode,
                              int low_rtt_nack_threshold_ms,
                              int high_rtt_nack_threshold_ms) {
  CriticalSectionScoped cs(crit_sect_);
  // Default to always having NACK enabled in hybrid mode.
  jitter_buffer_.SetNackMode(nackMode, low_rtt_nack_threshold_ms,
                             high_rtt_nack_threshold_ms);
  if (!master_) {
    state_ = kPassive;  // The dual decoder defaults to passive.
  }
}

void VCMReceiver::SetNackSettings(size_t max_nack_list_size,
                                  int max_packet_age_to_nack,
                                  int max_incomplete_time_ms) {
  jitter_buffer_.SetNackSettings(max_nack_list_size,
                                 max_packet_age_to_nack,
                                 max_incomplete_time_ms);
}

VCMNackMode VCMReceiver::NackMode() const {
  CriticalSectionScoped cs(crit_sect_);
  return jitter_buffer_.nack_mode();
}

VCMNackStatus VCMReceiver::NackList(uint16_t* nack_list,
                                    uint16_t size,
                                    uint16_t* nack_list_length) {
  bool request_key_frame = false;
  uint16_t* internal_nack_list = jitter_buffer_.GetNackList(
      nack_list_length, &request_key_frame);
  if (*nack_list_length > size) {
    *nack_list_length = 0;
    return kNackNeedMoreMemory;
  }
  if (internal_nack_list != NULL && *nack_list_length > 0) {
    memcpy(nack_list, internal_nack_list, *nack_list_length * sizeof(uint16_t));
  }
  if (request_key_frame) {
    return kNackKeyFrameRequest;
  }
  return kNackOk;
}

// Decide whether we should change decoder state. This should be done if the
// dual decoder has caught up with the decoder decoding with packet losses.
bool VCMReceiver::DualDecoderCaughtUp(VCMEncodedFrame* dual_frame,
                                      VCMReceiver& dual_receiver) const {
  if (dual_frame == NULL) {
    return false;
  }
  if (jitter_buffer_.LastDecodedTimestamp() == dual_frame->TimeStamp()) {
    dual_receiver.UpdateState(kWaitForPrimaryDecode);
    return true;
  }
  return false;
}

void VCMReceiver::CopyJitterBufferStateFromReceiver(
    const VCMReceiver& receiver) {
  jitter_buffer_.CopyFrom(receiver.jitter_buffer_);
}

VCMReceiverState VCMReceiver::State() const {
  CriticalSectionScoped cs(crit_sect_);
  return state_;
}

void VCMReceiver::SetDecodeErrorMode(VCMDecodeErrorMode decode_error_mode) {
  jitter_buffer_.SetDecodeErrorMode(decode_error_mode);
}

VCMDecodeErrorMode VCMReceiver::DecodeErrorMode() const {
  return jitter_buffer_.decode_error_mode();
}

int VCMReceiver::SetMinReceiverDelay(int desired_delay_ms) {
  CriticalSectionScoped cs(crit_sect_);
  if (desired_delay_ms < 0 || desired_delay_ms > kMaxReceiverDelayMs) {
    return -1;
  }
  max_video_delay_ms_ = desired_delay_ms + kMaxVideoDelayMs;
  // Initializing timing to the desired delay.
  timing_->set_min_playout_delay(desired_delay_ms);
  return 0;
}

int VCMReceiver::RenderBufferSizeMs() {
  uint32_t timestamp_start = 0u;
  uint32_t timestamp_end = 0u;
  // Render timestamps are computed just prior to decoding. Therefore this is
  // only an estimate based on frames' timestamps and current timing state.
  jitter_buffer_.RenderBufferSize(&timestamp_start, &timestamp_end);
  if (timestamp_start == timestamp_end) {
    return 0;
  }
  // Update timing.
  const int64_t now_ms = clock_->TimeInMilliseconds();
  timing_->SetJitterDelay(jitter_buffer_.EstimatedJitterMs());
  // Get render timestamps.
  uint32_t render_start = timing_->RenderTimeMs(timestamp_start, now_ms);
  uint32_t render_end = timing_->RenderTimeMs(timestamp_end, now_ms);
  return render_end - render_start;
}

void VCMReceiver::UpdateState(VCMReceiverState new_state) {
  CriticalSectionScoped cs(crit_sect_);
  assert(!(state_ == kPassive && new_state == kWaitForPrimaryDecode));
  state_ = new_state;
}

void VCMReceiver::UpdateState(const VCMEncodedFrame& frame) {
  if (jitter_buffer_.nack_mode() == kNoNack) {
    // Dual decoder mode has not been enabled.
    return;
  }
  // Update the dual receiver state.
  if (frame.Complete() && frame.FrameType() == kVideoFrameKey) {
    UpdateState(kPassive);
  }
  if (State() == kWaitForPrimaryDecode &&
      frame.Complete() && !frame.MissingFrame()) {
    UpdateState(kPassive);
  }
  if (frame.MissingFrame() || !frame.Complete()) {
    // State was corrupted, enable dual receiver.
    UpdateState(kReceiving);
  }
}
}  // namespace webrtc
<commit_msg>Avoid recursively taking critical section.<commit_after>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/modules/video_coding/main/source/receiver.h"

#include <assert.h>

#include "webrtc/modules/video_coding/main/source/encoded_frame.h"
#include "webrtc/modules/video_coding/main/source/internal_defines.h"
#include "webrtc/modules/video_coding/main/source/media_opt_util.h"
#include "webrtc/system_wrappers/interface/clock.h"
#include "webrtc/system_wrappers/interface/trace.h"
#include "webrtc/system_wrappers/interface/trace_event.h"

namespace webrtc {

enum { kMaxReceiverDelayMs = 10000 };

VCMReceiver::VCMReceiver(VCMTiming* timing,
                         Clock* clock,
                         EventFactory* event_factory,
                         int32_t vcm_id,
                         int32_t receiver_id,
                         bool master)
    : crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
      vcm_id_(vcm_id),
      clock_(clock),
      receiver_id_(receiver_id),
      master_(master),
      jitter_buffer_(clock_, event_factory, vcm_id, receiver_id, master),
      timing_(timing),
      render_wait_event_(event_factory->CreateEvent()),
      state_(kPassive),
      max_video_delay_ms_(kMaxVideoDelayMs) {}

VCMReceiver::~VCMReceiver() {
  render_wait_event_->Set();
  delete crit_sect_;
}

void VCMReceiver::Reset() {
  CriticalSectionScoped cs(crit_sect_);
  if (!jitter_buffer_.Running()) {
    jitter_buffer_.Start();
  } else {
    jitter_buffer_.Flush();
  }
  render_wait_event_->Reset();
  if (master_) {
    state_ = kReceiving;
  } else {
    state_ = kPassive;
  }
}

int32_t VCMReceiver::Initialize() {
  Reset();
  CriticalSectionScoped cs(crit_sect_);
  if (!master_) {
    SetNackMode(kNoNack, -1, -1);
  }
  return VCM_OK;
}

void VCMReceiver::UpdateRtt(uint32_t rtt) {
  jitter_buffer_.UpdateRtt(rtt);
}

int32_t VCMReceiver::InsertPacket(const VCMPacket& packet,
                                  uint16_t frame_width,
                                  uint16_t frame_height) {
  if (packet.frameType == kVideoFrameKey) {
    WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCoding,
                 VCMId(vcm_id_, receiver_id_),
                 "Inserting key frame packet seqnum=%u, timestamp=%u",
                 packet.seqNum, packet.timestamp);
  }

  // Insert the packet into the jitter buffer. The packet can either be empty or
  // contain media at this point.
  bool retransmitted = false;
  const VCMFrameBufferEnum ret = jitter_buffer_.InsertPacket(packet,
                                                             &retransmitted);
  if (ret == kOldPacket) {
    return VCM_OK;
  } else if (ret == kFlushIndicator) {
    return VCM_FLUSH_INDICATOR;
  } else if (ret < 0) {
    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCoding,
                 VCMId(vcm_id_, receiver_id_),
                 "Error inserting packet seqnum=%u, timestamp=%u",
                 packet.seqNum, packet.timestamp);
    return VCM_JITTER_BUFFER_ERROR;
  }
  if (ret == kCompleteSession && !retransmitted) {
    // We don't want to include timestamps which have suffered from
    // retransmission here, since we compensate with extra retransmission
    // delay within the jitter estimate.
    timing_->IncomingTimestamp(packet.timestamp, clock_->TimeInMilliseconds());
  }
  if (master_) {
    // Only trace the primary receiver to make it possible to parse and plot
    // the trace file.
    WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding,
                 VCMId(vcm_id_, receiver_id_),
                 "Packet seqnum=%u timestamp=%u inserted at %u",
                 packet.seqNum, packet.timestamp,
                 MaskWord64ToUWord32(clock_->TimeInMilliseconds()));
  }
  return VCM_OK;
}

VCMEncodedFrame* VCMReceiver::FrameForDecoding(
    uint16_t max_wait_time_ms,
    int64_t& next_render_time_ms,
    bool render_timing,
    VCMReceiver* dual_receiver) {
  const int64_t start_time_ms = clock_->TimeInMilliseconds();
  uint32_t frame_timestamp = 0;
  // Exhaust wait time to get a complete frame for decoding.
  bool found_frame = jitter_buffer_.NextCompleteTimestamp(
      max_wait_time_ms, &frame_timestamp);

  if (!found_frame) {
    // Get an incomplete frame when enabled.
    const bool dual_receiver_enabled_and_passive = (dual_receiver != NULL &&
        dual_receiver->State() == kPassive &&
        dual_receiver->NackMode() == kNack);
    if (dual_receiver_enabled_and_passive &&
        !jitter_buffer_.CompleteSequenceWithNextFrame()) {
      // Jitter buffer state might get corrupt with this frame.
      dual_receiver->CopyJitterBufferStateFromReceiver(*this);
    }
    found_frame = jitter_buffer_.NextMaybeIncompleteTimestamp(
        &frame_timestamp);
  }

  if (!found_frame) {
    return NULL;
  }

  // We have a frame - Set timing and render timestamp.
  timing_->SetJitterDelay(jitter_buffer_.EstimatedJitterMs());
  const int64_t now_ms = clock_->TimeInMilliseconds();
  timing_->UpdateCurrentDelay(frame_timestamp);
  next_render_time_ms = timing_->RenderTimeMs(frame_timestamp, now_ms);
  // Check render timing.
  bool timing_error = false;
  // Assume that render timing errors are due to changes in the video stream.
  if (next_render_time_ms < 0) {
    timing_error = true;
  } else if (abs(next_render_time_ms - now_ms) > max_video_delay_ms_) {
    WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCoding,
                 VCMId(vcm_id_, receiver_id_),
                 "This frame is out of our delay bounds, resetting jitter "
                 "buffer: %d > %d",
                 static_cast<int>(abs(next_render_time_ms - now_ms)),
                 max_video_delay_ms_);
    timing_error = true;
  } else if (static_cast<int>(timing_->TargetVideoDelay()) >
             max_video_delay_ms_) {
    WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCoding,
                 VCMId(vcm_id_, receiver_id_),
                 "More than %u ms target delay. Flushing jitter buffer and"
                 "resetting timing.", max_video_delay_ms_);
    timing_error = true;
  }

  if (timing_error) {
    // Timing error => reset timing and flush the jitter buffer.
    jitter_buffer_.Flush();
    timing_->Reset();
    return NULL;
  }

  if (!render_timing) {
    // Decode frame as close as possible to the render timestamp.
    const int32_t available_wait_time = max_wait_time_ms -
        static_cast<int32_t>(clock_->TimeInMilliseconds() - start_time_ms);
    uint16_t new_max_wait_time = static_cast<uint16_t>(
        VCM_MAX(available_wait_time, 0));
    uint32_t wait_time_ms = timing_->MaxWaitingTime(
        next_render_time_ms, clock_->TimeInMilliseconds());
    if (new_max_wait_time < wait_time_ms) {
      // We're not allowed to wait until the frame is supposed to be rendered,
      // waiting as long as we're allowed to avoid busy looping, and then return
      // NULL. Next call to this function might return the frame.
      render_wait_event_->Wait(max_wait_time_ms);
      return NULL;
    }
    // Wait until it's time to render.
    render_wait_event_->Wait(wait_time_ms);
  }

  // Extract the frame from the jitter buffer and set the render time.
  VCMEncodedFrame* frame = jitter_buffer_.ExtractAndSetDecode(frame_timestamp);
  if (frame == NULL) {
    return NULL;
  }
  frame->SetRenderTime(next_render_time_ms);
  TRACE_EVENT_ASYNC_STEP1("webrtc", "Video", frame->TimeStamp(),
                          "SetRenderTS", "render_time", next_render_time_ms);
  if (dual_receiver != NULL) {
    dual_receiver->UpdateState(*frame);
  }
  if (!frame->Complete()) {
    // Update stats for incomplete frames.
    bool retransmitted = false;
    const int64_t last_packet_time_ms =
        jitter_buffer_.LastPacketTime(frame, &retransmitted);
    if (last_packet_time_ms >= 0 && !retransmitted) {
      // We don't want to include timestamps which have suffered from
      // retransmission here, since we compensate with extra retransmission
      // delay within the jitter estimate.
      timing_->IncomingTimestamp(frame_timestamp, last_packet_time_ms);
    }
  }
  return frame;
}

void VCMReceiver::ReleaseFrame(VCMEncodedFrame* frame) {
  jitter_buffer_.ReleaseFrame(frame);
}

void VCMReceiver::ReceiveStatistics(uint32_t* bitrate,
                                    uint32_t* framerate) {
  assert(bitrate);
  assert(framerate);
  jitter_buffer_.IncomingRateStatistics(framerate, bitrate);
}

void VCMReceiver::ReceivedFrameCount(VCMFrameCount* frame_count) const {
  assert(frame_count);
  jitter_buffer_.FrameStatistics(&frame_count->numDeltaFrames,
                                 &frame_count->numKeyFrames);
}

uint32_t VCMReceiver::DiscardedPackets() const {
  return jitter_buffer_.num_discarded_packets();
}

void VCMReceiver::SetNackMode(VCMNackMode nackMode,
                              int low_rtt_nack_threshold_ms,
                              int high_rtt_nack_threshold_ms) {
  CriticalSectionScoped cs(crit_sect_);
  // Default to always having NACK enabled in hybrid mode.
  jitter_buffer_.SetNackMode(nackMode, low_rtt_nack_threshold_ms,
                             high_rtt_nack_threshold_ms);
  if (!master_) {
    state_ = kPassive;  // The dual decoder defaults to passive.
  }
}

void VCMReceiver::SetNackSettings(size_t max_nack_list_size,
                                  int max_packet_age_to_nack,
                                  int max_incomplete_time_ms) {
  jitter_buffer_.SetNackSettings(max_nack_list_size,
                                 max_packet_age_to_nack,
                                 max_incomplete_time_ms);
}

VCMNackMode VCMReceiver::NackMode() const {
  CriticalSectionScoped cs(crit_sect_);
  return jitter_buffer_.nack_mode();
}

VCMNackStatus VCMReceiver::NackList(uint16_t* nack_list,
                                    uint16_t size,
                                    uint16_t* nack_list_length) {
  bool request_key_frame = false;
  uint16_t* internal_nack_list = jitter_buffer_.GetNackList(
      nack_list_length, &request_key_frame);
  if (*nack_list_length > size) {
    *nack_list_length = 0;
    return kNackNeedMoreMemory;
  }
  if (internal_nack_list != NULL && *nack_list_length > 0) {
    memcpy(nack_list, internal_nack_list, *nack_list_length * sizeof(uint16_t));
  }
  if (request_key_frame) {
    return kNackKeyFrameRequest;
  }
  return kNackOk;
}

// Decide whether we should change decoder state. This should be done if the
// dual decoder has caught up with the decoder decoding with packet losses.
bool VCMReceiver::DualDecoderCaughtUp(VCMEncodedFrame* dual_frame,
                                      VCMReceiver& dual_receiver) const {
  if (dual_frame == NULL) {
    return false;
  }
  if (jitter_buffer_.LastDecodedTimestamp() == dual_frame->TimeStamp()) {
    dual_receiver.UpdateState(kWaitForPrimaryDecode);
    return true;
  }
  return false;
}

void VCMReceiver::CopyJitterBufferStateFromReceiver(
    const VCMReceiver& receiver) {
  jitter_buffer_.CopyFrom(receiver.jitter_buffer_);
}

VCMReceiverState VCMReceiver::State() const {
  CriticalSectionScoped cs(crit_sect_);
  return state_;
}

void VCMReceiver::SetDecodeErrorMode(VCMDecodeErrorMode decode_error_mode) {
  jitter_buffer_.SetDecodeErrorMode(decode_error_mode);
}

VCMDecodeErrorMode VCMReceiver::DecodeErrorMode() const {
  return jitter_buffer_.decode_error_mode();
}

int VCMReceiver::SetMinReceiverDelay(int desired_delay_ms) {
  CriticalSectionScoped cs(crit_sect_);
  if (desired_delay_ms < 0 || desired_delay_ms > kMaxReceiverDelayMs) {
    return -1;
  }
  max_video_delay_ms_ = desired_delay_ms + kMaxVideoDelayMs;
  // Initializing timing to the desired delay.
  timing_->set_min_playout_delay(desired_delay_ms);
  return 0;
}

int VCMReceiver::RenderBufferSizeMs() {
  uint32_t timestamp_start = 0u;
  uint32_t timestamp_end = 0u;
  // Render timestamps are computed just prior to decoding. Therefore this is
  // only an estimate based on frames' timestamps and current timing state.
  jitter_buffer_.RenderBufferSize(&timestamp_start, &timestamp_end);
  if (timestamp_start == timestamp_end) {
    return 0;
  }
  // Update timing.
  const int64_t now_ms = clock_->TimeInMilliseconds();
  timing_->SetJitterDelay(jitter_buffer_.EstimatedJitterMs());
  // Get render timestamps.
  uint32_t render_start = timing_->RenderTimeMs(timestamp_start, now_ms);
  uint32_t render_end = timing_->RenderTimeMs(timestamp_end, now_ms);
  return render_end - render_start;
}

void VCMReceiver::UpdateState(VCMReceiverState new_state) {
  CriticalSectionScoped cs(crit_sect_);
  assert(!(state_ == kPassive && new_state == kWaitForPrimaryDecode));
  state_ = new_state;
}

void VCMReceiver::UpdateState(const VCMEncodedFrame& frame) {
  if (jitter_buffer_.nack_mode() == kNoNack) {
    // Dual decoder mode has not been enabled.
    return;
  }
  // Update the dual receiver state.
  if (frame.Complete() && frame.FrameType() == kVideoFrameKey) {
    UpdateState(kPassive);
  }
  if (State() == kWaitForPrimaryDecode &&
      frame.Complete() && !frame.MissingFrame()) {
    UpdateState(kPassive);
  }
  if (frame.MissingFrame() || !frame.Complete()) {
    // State was corrupted, enable dual receiver.
    UpdateState(kReceiving);
  }
}
}  // namespace webrtc
<|endoftext|>


<commit_before>#include "GraphicsHandler.h"

int GraphicsHandler::IncreaseArraySize()
{
	GraphicsComponent** newArray = new GraphicsComponent*[this->m_maxGraphicsComponents + ARRAY_INC];

	for (int i = 0; i < this->m_maxGraphicsComponents; i++)
	{
		newArray[i] = this->m_graphicsComponents[i];
	}
	delete[] this->m_graphicsComponents;
	this->m_graphicsComponents = newArray;
	this->m_maxGraphicsComponents += ARRAY_INC;

	return 1;
}

int GraphicsHandler::DecreaseArraySize()
{
	this->m_maxGraphicsComponents -= ARRAY_INC;
	GraphicsComponent** newArray = new GraphicsComponent*[this->m_maxGraphicsComponents];

	for (int i = 0; i < this->m_maxGraphicsComponents; i++)
	{
		newArray[i] = this->m_graphicsComponents[i];
	}

	for (int i = this->m_maxGraphicsComponents; i < this->m_maxGraphicsComponents + ARRAY_INC; i++)
	{
		if (this->m_graphicsComponents[i])
		{
			delete this->m_graphicsComponents[i];
		}
	}

	delete[] this->m_graphicsComponents;
	this->m_graphicsComponents = newArray;

	return 1;
}

GraphicsHandler::GraphicsHandler()
{
	this->m_d3dHandler = nullptr;
	this->m_deferredSH = nullptr;
	this->m_lightSH = nullptr;
	this->m_indexBuffer = nullptr;
	this->m_vertexBuffer = nullptr;
	this->m_camera = nullptr;
	this->m_graphicsComponents = nullptr;
	this->m_nrOfGraphicsComponents = 0;
	this->m_maxGraphicsComponents = 5;
}

GraphicsHandler::~GraphicsHandler()
{
}

int GraphicsHandler::Initialize(HWND * windowHandle, const DirectX::XMINT2& resolution)
{
	this->m_d3dHandler = new Direct3DHandler;
	if (this->m_d3dHandler->Initialize(windowHandle, resolution))
	{
		return 1;
	}
	Resources::ResourceHandler::GetInstance()->LoadLevel(UINT(1337)); //placeholder id

	this->m_deferredSH = new DeferredShaderHandler;
	if (this->m_deferredSH->Initialize(this->m_d3dHandler->GetDevice(), windowHandle, resolution))
	{
		return 1;
	}

	this->m_lightSH = new LightShaderHandler;
	if (this->m_lightSH->Initialize(this->m_d3dHandler->GetDevice(), windowHandle, resolution))
	{
		return 1;
	}

	this->m_camera = new Camera;
	this->m_camera->Initialize();

	//Setup projection matrix
	//fieldOfView = 3.141592654f / 4.0f;
	float fieldOfView = (float)DirectX::XM_PI / 4.0f;
	float screenAspect = (float)resolution.x / (float)resolution.y;

	DirectX::XMStoreFloat4x4(&m_projectionMatrix, DirectX::XMMatrixPerspectiveFovLH(fieldOfView, screenAspect, 0.1f, 1000.0f));

	this->CreateTriangle();

	this->m_graphicsComponents = new GraphicsComponent*[this->m_maxGraphicsComponents];
	for (int i = 0; i < this->m_maxGraphicsComponents; i++) {
		this->m_graphicsComponents[i] = nullptr;
	}

	DirectX::XMMATRIX tempWorld = DirectX::XMMatrixIdentity();
	//DirectX::XMFLOAT4X4 worldMatrix;
	//DirectX::XMStoreFloat4x4(&worldMatrix, tempWorld);

	this->m_graphicsComponents[this->m_nrOfGraphicsComponents] = new GraphicsComponent;
	this->m_graphicsComponents[this->m_nrOfGraphicsComponents]->worldMatrix = tempWorld;
	this->m_nrOfGraphicsComponents++;

	tempWorld = DirectX::XMMatrixTranslation(1.f, 0.f, 6.f);
	tempWorld = DirectX::XMMatrixMultiply(tempWorld, DirectX::XMMatrixRotationZ(.3f));
	//DirectX::XMStoreFloat4x4(&worldMatrix, tempWorld);
	this->m_graphicsComponents[this->m_nrOfGraphicsComponents] = new GraphicsComponent;
	this->m_graphicsComponents[this->m_nrOfGraphicsComponents]->worldMatrix = tempWorld;
	this->m_nrOfGraphicsComponents++;

	tempWorld = DirectX::XMMatrixTranslation(-1.f, 0.5f, 6.f);
	tempWorld = DirectX::XMMatrixMultiply(tempWorld, DirectX::XMMatrixRotationZ(.3f));
	tempWorld = DirectX::XMMatrixMultiply(tempWorld, DirectX::XMMatrixScaling(0.5f, 0.5f, 0.5f));
	//DirectX::XMStoreFloat4x4(&worldMatrix, tempWorld);
	this->m_graphicsComponents[this->m_nrOfGraphicsComponents] = new GraphicsComponent;
	this->m_graphicsComponents[this->m_nrOfGraphicsComponents]->worldMatrix = tempWorld;
	this->m_nrOfGraphicsComponents++;

	return 0;
}

Camera* GraphicsHandler::SetCamera(Camera * newCamera)
{
	int result = 1;
	Camera* tempCam = this->m_camera;
	this->m_camera = newCamera;
	return tempCam;
}

int GraphicsHandler::Render()
{

	this->m_deferredSH->ClearRenderTargetViews(this->m_d3dHandler->GetDeviceContext());

	DirectX::XMMATRIX viewMatrix;
	this->m_camera->GetViewMatrix(viewMatrix);

	this->SetTriangle();

	this->m_deferredSH->SetActive(this->m_d3dHandler->GetDeviceContext(), ShaderLib::ShaderType::Normal);

	ShaderLib::DeferredConstantBufferWorld* shaderParamsWorld = new ShaderLib::DeferredConstantBufferWorld;
	ShaderLib::DeferredConstantBufferVP* shaderParamsVP = new ShaderLib::DeferredConstantBufferVP;
	ShaderLib::DeferredConstantBufferWorldxm * shaderParamsXM = new ShaderLib::DeferredConstantBufferWorldxm;

	shaderParamsVP->viewMatrix = *this->m_camera->GetViewMatrix();
	shaderParamsVP->projectionMatrix = this->m_projectionMatrix;

	this->m_deferredSH->SetShaderParameters(this->m_d3dHandler->GetDeviceContext(), shaderParamsVP, ShaderLib::VIEW_PROJECTION);

	/*TEMP*/
	Resources::Model* modelPtr;
	Resources::ResourceHandler::GetInstance()->GetModel(UINT(111337),modelPtr);

	Resources::Mesh* meshPtr = modelPtr->GetMesh();
	ID3D11Buffer* vBuf = meshPtr->GetVerticesBuffer();
	ID3D11Buffer* iBuf = meshPtr->GetIndicesBuffer();
	UINT32 size = sizeof(Resources::Mesh::Vertex);
	UINT32 offset = 0;
	ID3D11DeviceContext* dev = m_d3dHandler->GetDeviceContext();
	dev->IASetVertexBuffers(0, 1, &vBuf, &size, &offset);
	m_d3dHandler->GetDeviceContext()->IASetIndexBuffer(iBuf, DXGI_FORMAT::DXGI_FORMAT_R32_UINT, 0);

	Resources::Material * mat  = modelPtr->GetMaterial();
	Resources::Texture** textures = mat->GetAllTextures();
	ID3D11ShaderResourceView* resViews[5];
	UINT numViews = 0;
	for (size_t i = 0; i < 5; i++)
	{
		if (textures[i] == nullptr)
			continue;

		resViews[numViews] = textures[i]->GetResourceView();
		numViews += 1;
	}
	m_d3dHandler->GetDeviceContext()->PSSetShaderResources(0, numViews, resViews);
	/********/

	////TEST ROTATION
	//static DirectX::XMMATRIX rotation = DirectX::XMMatrixIdentity();
	//rotation = DirectX::XMMatrixMultiply(rotation, DirectX::XMMatrixRotationY(0.0000000005f));
	//this->m_graphicsComponents[0]->worldMatrix = DirectX::XMMatrixMultiply(rotation, this->m_graphicsComponents[0]->worldMatrix);
	////END TEST ROTATION

	shaderParamsWorld->worldMatrix = DirectX::XMFLOAT4X4();

	for (int i = 0; i < this->m_nrOfGraphicsComponents; i++)
	{
		shaderParamsXM->worldMatrix = this->m_graphicsComponents[i]->worldMatrix;

		//DirectX::XMStoreFloat4x4(&shaderParamsWorld->worldMatrix, this->m_graphicsComponents[i]->worldMatrix);
		this->m_deferredSH->SetShaderParameters(this->m_d3dHandler->GetDeviceContext(), shaderParamsXM, ShaderLib::WORLD);
		//this->m_d3dHandler->GetDeviceContext()->DrawIndexed(3, 0, 0);

		this->m_d3dHandler->GetDeviceContext()->DrawIndexed(meshPtr->GetNumIndices(), 0, 0);
	}

	delete shaderParamsVP;
	delete shaderParamsWorld;

	this->m_d3dHandler->ClearDepthAndRTV(this->m_deferredSH->GetDSV());
	this->m_d3dHandler->SetBackBuffer(this->m_deferredSH->GetDSV());
	this->m_lightSH->SetActive(this->m_d3dHandler->GetDeviceContext(), ShaderLib::ShaderType::Normal);

	ShaderLib::LightConstantBuffer* lShaderParams = new ShaderLib::LightConstantBuffer;
	lShaderParams->camPos = this->m_camera->GetCameraPos();
	lShaderParams->camDir = this->m_camera->GetLookAt();

	this->m_lightSH->SetShaderParameters(this->m_d3dHandler->GetDeviceContext(), lShaderParams, this->m_deferredSH->GetShaderResourceViews());
	delete lShaderParams;
	this->m_d3dHandler->GetDeviceContext()->DrawIndexed(6, 0, 0);

	this->m_lightSH->ResetPSShaderResources(this->m_d3dHandler->GetDeviceContext());

	this->m_d3dHandler->PresentScene();

	return 0;
}

void GraphicsHandler::Shutdown()
{
	if (this->m_d3dHandler)
	{
		this->m_d3dHandler->Shutdown();
		delete this->m_d3dHandler;
		this->m_d3dHandler = nullptr;
	}
	if (this->m_deferredSH)
	{
		this->m_deferredSH->Shutdown();
		delete this->m_deferredSH;
		this->m_deferredSH = nullptr;
	}
	if (this->m_lightSH)
	{
		this->m_lightSH->Shutdown();
		delete this->m_lightSH;
		this->m_lightSH = nullptr;
	}
	if (this->m_indexBuffer)
	{
		this->m_indexBuffer->Release();
		this->m_indexBuffer = nullptr;
	}
	if (this->m_vertexBuffer)
	{
		this->m_vertexBuffer->Release();
		this->m_vertexBuffer = nullptr;
	}
	if (this->m_windowHandle)
	{
		this->m_windowHandle = nullptr;
	}
	for (int i = 0; i < this->m_nrOfGraphicsComponents; i++)
	{
		if (this->m_graphicsComponents[i])
		{
			delete this->m_graphicsComponents[i];
			this->m_graphicsComponents[i] = nullptr;
		}
	}
	delete[] this->m_graphicsComponents;
}

int GraphicsHandler::CreateTriangle()
{
	DirectX::XMFLOAT3 vertices[3];
	unsigned long indices[3];
	int sizeVertices = 3;
	int sizeIndices = 3;
	D3D11_BUFFER_DESC vertexBufferDesc;
	D3D11_BUFFER_DESC indexBufferDesc;
	D3D11_SUBRESOURCE_DATA vertexData;
	D3D11_SUBRESOURCE_DATA indexData;
	HRESULT hresult;

	vertices[0] = DirectX::XMFLOAT3(-.5f, -.5f, 2.0f);  //bottom left

	vertices[1] = DirectX::XMFLOAT3(0.0f, .5f, 2.0f);  //top mid

	vertices[2] = DirectX::XMFLOAT3(.5f, -.5f, 2.0f);  //bottom right

														 //Load the index array with data
	for (int i = 0; i < sizeIndices; i++)
	{
		indices[i] = i;
	}

	//Set the description of the static vertex buffer
	ZeroMemory(&vertexBufferDesc, sizeof(vertexBufferDesc));
	vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
	vertexBufferDesc.ByteWidth = sizeof(DirectX::XMFLOAT3) * sizeVertices;
	vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	vertexBufferDesc.CPUAccessFlags = 0;
	vertexBufferDesc.MiscFlags = 0;
	vertexBufferDesc.StructureByteStride = 0;

	//Give the subresource structure a pointer to the vertex data
	ZeroMemory(&vertexData, sizeof(vertexData));
	vertexData.pSysMem = &vertices;
	vertexData.SysMemPitch = 0;
	vertexData.SysMemSlicePitch = 0;

	//Create the vertex buffer
	hresult = this->m_d3dHandler->GetDevice()->CreateBuffer(&vertexBufferDesc, &vertexData, &this->m_vertexBuffer);
	if (FAILED(hresult)) {
		return 1;
	}

	//Set up the description of the static index buffer
	ZeroMemory(&indexBufferDesc, sizeof(indexBufferDesc));
	indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
	indexBufferDesc.ByteWidth = sizeof(unsigned long) * sizeIndices;
	indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
	indexBufferDesc.CPUAccessFlags = 0;
	indexBufferDesc.MiscFlags = 0;
	indexBufferDesc.StructureByteStride = 0;

	ZeroMemory(&indexData, sizeof(indexData));
	indexData.pSysMem = &indices;
	indexData.SysMemPitch = 0;
	indexData.SysMemSlicePitch = 0;

	//Create the index buffer
	hresult = this->m_d3dHandler->GetDevice()->CreateBuffer(&indexBufferDesc, &indexData, &this->m_indexBuffer);
	if (FAILED(hresult)) {
		return 1;
	}

	return 0;
}

int GraphicsHandler::SetTriangle()
{
	unsigned int stride;
	unsigned offset;

	//Set vertex buffer stride and offset
	stride = sizeof(DirectX::XMFLOAT3);
	offset = 0;

	//Set the vertex buffer to active in the input assembly so it can rendered
	this->m_d3dHandler->GetDeviceContext()->IASetVertexBuffers(0, 1, &this->m_vertexBuffer, &stride, &offset);

	//Set the index buffer to active in the input assembler so it can be rendered
	this->m_d3dHandler->GetDeviceContext()->IASetIndexBuffer(this->m_indexBuffer, DXGI_FORMAT_R32_UINT, 0);

	//Set the type od primitiv that should be rendered from this vertex buffer, in this case triangles
	this->m_d3dHandler->GetDeviceContext()->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

	return 0;
}
<commit_msg>UPDATE cleanup<commit_after>#include "GraphicsHandler.h"

int GraphicsHandler::IncreaseArraySize()
{
	GraphicsComponent** newArray = new GraphicsComponent*[this->m_maxGraphicsComponents + ARRAY_INC];

	for (int i = 0; i < this->m_maxGraphicsComponents; i++)
	{
		newArray[i] = this->m_graphicsComponents[i];
	}
	delete[] this->m_graphicsComponents;
	this->m_graphicsComponents = newArray;
	this->m_maxGraphicsComponents += ARRAY_INC;

	return 1;
}

int GraphicsHandler::DecreaseArraySize()
{
	this->m_maxGraphicsComponents -= ARRAY_INC;
	GraphicsComponent** newArray = new GraphicsComponent*[this->m_maxGraphicsComponents];

	for (int i = 0; i < this->m_maxGraphicsComponents; i++)
	{
		newArray[i] = this->m_graphicsComponents[i];
	}

	for (int i = this->m_maxGraphicsComponents; i < this->m_maxGraphicsComponents + ARRAY_INC; i++)
	{
		if (this->m_graphicsComponents[i])
		{
			delete this->m_graphicsComponents[i];
		}
	}

	delete[] this->m_graphicsComponents;
	this->m_graphicsComponents = newArray;

	return 1;
}

GraphicsHandler::GraphicsHandler()
{
	this->m_d3dHandler = nullptr;
	this->m_deferredSH = nullptr;
	this->m_lightSH = nullptr;
	this->m_indexBuffer = nullptr;
	this->m_vertexBuffer = nullptr;
	this->m_camera = nullptr;
	this->m_graphicsComponents = nullptr;
	this->m_nrOfGraphicsComponents = 0;
	this->m_maxGraphicsComponents = 5;
}

GraphicsHandler::~GraphicsHandler()
{
}

int GraphicsHandler::Initialize(HWND * windowHandle, const DirectX::XMINT2& resolution)
{
	this->m_d3dHandler = new Direct3DHandler;
	if (this->m_d3dHandler->Initialize(windowHandle, resolution))
	{
		return 1;
	}
	Resources::ResourceHandler::GetInstance()->LoadLevel(UINT(1337)); //placeholder id

	this->m_deferredSH = new DeferredShaderHandler;
	if (this->m_deferredSH->Initialize(this->m_d3dHandler->GetDevice(), windowHandle, resolution))
	{
		return 1;
	}

	this->m_lightSH = new LightShaderHandler;
	if (this->m_lightSH->Initialize(this->m_d3dHandler->GetDevice(), windowHandle, resolution))
	{
		return 1;
	}

	this->m_camera = new Camera;
	this->m_camera->Initialize();

	//Setup projection matrix
	//fieldOfView = 3.141592654f / 4.0f;
	float fieldOfView = (float)DirectX::XM_PI / 4.0f;
	float screenAspect = (float)resolution.x / (float)resolution.y;

	DirectX::XMStoreFloat4x4(&m_projectionMatrix, DirectX::XMMatrixPerspectiveFovLH(fieldOfView, screenAspect, 0.1f, 1000.0f));

	this->CreateTriangle();

	this->m_graphicsComponents = new GraphicsComponent*[this->m_maxGraphicsComponents];
	for (int i = 0; i < this->m_maxGraphicsComponents; i++) {
		this->m_graphicsComponents[i] = nullptr;
	}

	DirectX::XMMATRIX tempWorld = DirectX::XMMatrixIdentity();
	//DirectX::XMFLOAT4X4 worldMatrix;
	//DirectX::XMStoreFloat4x4(&worldMatrix, tempWorld);

	this->m_graphicsComponents[this->m_nrOfGraphicsComponents] = new GraphicsComponent;
	this->m_graphicsComponents[this->m_nrOfGraphicsComponents]->worldMatrix = tempWorld;
	this->m_nrOfGraphicsComponents++;

	tempWorld = DirectX::XMMatrixTranslation(1.f, 0.f, 6.f);
	tempWorld = DirectX::XMMatrixMultiply(tempWorld, DirectX::XMMatrixRotationZ(.3f));
	//DirectX::XMStoreFloat4x4(&worldMatrix, tempWorld);
	this->m_graphicsComponents[this->m_nrOfGraphicsComponents] = new GraphicsComponent;
	this->m_graphicsComponents[this->m_nrOfGraphicsComponents]->worldMatrix = tempWorld;
	this->m_nrOfGraphicsComponents++;

	tempWorld = DirectX::XMMatrixTranslation(-1.f, 0.5f, 6.f);
	tempWorld = DirectX::XMMatrixMultiply(tempWorld, DirectX::XMMatrixRotationZ(.3f));
	tempWorld = DirectX::XMMatrixMultiply(tempWorld, DirectX::XMMatrixScaling(0.5f, 0.5f, 0.5f));
	//DirectX::XMStoreFloat4x4(&worldMatrix, tempWorld);
	this->m_graphicsComponents[this->m_nrOfGraphicsComponents] = new GraphicsComponent;
	this->m_graphicsComponents[this->m_nrOfGraphicsComponents]->worldMatrix = tempWorld;
	this->m_nrOfGraphicsComponents++;

	return 0;
}

Camera* GraphicsHandler::SetCamera(Camera * newCamera)
{
	int result = 1;
	Camera* tempCam = this->m_camera;
	this->m_camera = newCamera;
	return tempCam;
}

int GraphicsHandler::Render()
{

	this->m_deferredSH->ClearRenderTargetViews(this->m_d3dHandler->GetDeviceContext());

	DirectX::XMMATRIX viewMatrix;
	this->m_camera->GetViewMatrix(viewMatrix);

	this->SetTriangle();

	this->m_deferredSH->SetActive(this->m_d3dHandler->GetDeviceContext(), ShaderLib::ShaderType::Normal);

	ShaderLib::DeferredConstantBufferWorld* shaderParamsWorld = new ShaderLib::DeferredConstantBufferWorld;
	ShaderLib::DeferredConstantBufferVP* shaderParamsVP = new ShaderLib::DeferredConstantBufferVP;
	ShaderLib::DeferredConstantBufferWorldxm * shaderParamsXM = new ShaderLib::DeferredConstantBufferWorldxm;

	shaderParamsVP->viewMatrix = *this->m_camera->GetViewMatrix();
	shaderParamsVP->projectionMatrix = this->m_projectionMatrix;

	this->m_deferredSH->SetShaderParameters(this->m_d3dHandler->GetDeviceContext(), shaderParamsVP, ShaderLib::VIEW_PROJECTION);

	/*TEMP*/
	Resources::Model* modelPtr;
	Resources::ResourceHandler::GetInstance()->GetModel(UINT(111337),modelPtr);

	Resources::Mesh* meshPtr = modelPtr->GetMesh();
	ID3D11Buffer* vBuf = meshPtr->GetVerticesBuffer();
	ID3D11Buffer* iBuf = meshPtr->GetIndicesBuffer();
	UINT32 size = sizeof(Resources::Mesh::Vertex);
	UINT32 offset = 0;
	ID3D11DeviceContext* dev = m_d3dHandler->GetDeviceContext();
	dev->IASetVertexBuffers(0, 1, &vBuf, &size, &offset);
	m_d3dHandler->GetDeviceContext()->IASetIndexBuffer(iBuf, DXGI_FORMAT::DXGI_FORMAT_R32_UINT, 0);

	Resources::Material * mat  = modelPtr->GetMaterial();
	Resources::Texture** textures = mat->GetAllTextures();
	ID3D11ShaderResourceView* resViews[5];
	UINT numViews = 0;
	for (size_t i = 0; i < 5; i++)
	{
		if (textures[i] == nullptr)
			continue;

		resViews[numViews] = textures[i]->GetResourceView();
		numViews += 1;
	}
	m_d3dHandler->GetDeviceContext()->PSSetShaderResources(0, numViews, resViews);
	/********/

	////TEST ROTATION
	//static DirectX::XMMATRIX rotation = DirectX::XMMatrixIdentity();
	//rotation = DirectX::XMMatrixMultiply(rotation, DirectX::XMMatrixRotationY(0.0000000005f));
	//this->m_graphicsComponents[0]->worldMatrix = DirectX::XMMatrixMultiply(rotation, this->m_graphicsComponents[0]->worldMatrix);
	////END TEST ROTATION

	for (int i = 0; i < this->m_nrOfGraphicsComponents; i++)
	{
		shaderParamsXM->worldMatrix = this->m_graphicsComponents[i]->worldMatrix;

		//DirectX::XMStoreFloat4x4(&shaderParamsWorld->worldMatrix, this->m_graphicsComponents[i]->worldMatrix);
		this->m_deferredSH->SetShaderParameters(this->m_d3dHandler->GetDeviceContext(), shaderParamsXM, ShaderLib::WORLD);
		//this->m_d3dHandler->GetDeviceContext()->DrawIndexed(3, 0, 0);

		this->m_d3dHandler->GetDeviceContext()->DrawIndexed(meshPtr->GetNumIndices(), 0, 0);
	}

	delete shaderParamsVP;
	delete shaderParamsWorld;

	this->m_d3dHandler->ClearDepthAndRTV(this->m_deferredSH->GetDSV());
	this->m_d3dHandler->SetBackBuffer(this->m_deferredSH->GetDSV());
	this->m_lightSH->SetActive(this->m_d3dHandler->GetDeviceContext(), ShaderLib::ShaderType::Normal);

	ShaderLib::LightConstantBuffer* lShaderParams = new ShaderLib::LightConstantBuffer;
	lShaderParams->camPos = this->m_camera->GetCameraPos();
	lShaderParams->camDir = this->m_camera->GetLookAt();

	this->m_lightSH->SetShaderParameters(this->m_d3dHandler->GetDeviceContext(), lShaderParams, this->m_deferredSH->GetShaderResourceViews());
	delete lShaderParams;
	this->m_d3dHandler->GetDeviceContext()->DrawIndexed(6, 0, 0);

	this->m_lightSH->ResetPSShaderResources(this->m_d3dHandler->GetDeviceContext());

	this->m_d3dHandler->PresentScene();

	return 0;
}

void GraphicsHandler::Shutdown()
{
	if (this->m_d3dHandler)
	{
		this->m_d3dHandler->Shutdown();
		delete this->m_d3dHandler;
		this->m_d3dHandler = nullptr;
	}
	if (this->m_deferredSH)
	{
		this->m_deferredSH->Shutdown();
		delete this->m_deferredSH;
		this->m_deferredSH = nullptr;
	}
	if (this->m_lightSH)
	{
		this->m_lightSH->Shutdown();
		delete this->m_lightSH;
		this->m_lightSH = nullptr;
	}
	if (this->m_indexBuffer)
	{
		this->m_indexBuffer->Release();
		this->m_indexBuffer = nullptr;
	}
	if (this->m_vertexBuffer)
	{
		this->m_vertexBuffer->Release();
		this->m_vertexBuffer = nullptr;
	}
	if (this->m_windowHandle)
	{
		this->m_windowHandle = nullptr;
	}
	for (int i = 0; i < this->m_nrOfGraphicsComponents; i++)
	{
		if (this->m_graphicsComponents[i])
		{
			delete this->m_graphicsComponents[i];
			this->m_graphicsComponents[i] = nullptr;
		}
	}
	delete[] this->m_graphicsComponents;
}

int GraphicsHandler::CreateTriangle()
{
	DirectX::XMFLOAT3 vertices[3];
	unsigned long indices[3];
	int sizeVertices = 3;
	int sizeIndices = 3;
	D3D11_BUFFER_DESC vertexBufferDesc;
	D3D11_BUFFER_DESC indexBufferDesc;
	D3D11_SUBRESOURCE_DATA vertexData;
	D3D11_SUBRESOURCE_DATA indexData;
	HRESULT hresult;

	vertices[0] = DirectX::XMFLOAT3(-.5f, -.5f, 2.0f);  //bottom left

	vertices[1] = DirectX::XMFLOAT3(0.0f, .5f, 2.0f);  //top mid

	vertices[2] = DirectX::XMFLOAT3(.5f, -.5f, 2.0f);  //bottom right

														 //Load the index array with data
	for (int i = 0; i < sizeIndices; i++)
	{
		indices[i] = i;
	}

	//Set the description of the static vertex buffer
	ZeroMemory(&vertexBufferDesc, sizeof(vertexBufferDesc));
	vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
	vertexBufferDesc.ByteWidth = sizeof(DirectX::XMFLOAT3) * sizeVertices;
	vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	vertexBufferDesc.CPUAccessFlags = 0;
	vertexBufferDesc.MiscFlags = 0;
	vertexBufferDesc.StructureByteStride = 0;

	//Give the subresource structure a pointer to the vertex data
	ZeroMemory(&vertexData, sizeof(vertexData));
	vertexData.pSysMem = &vertices;
	vertexData.SysMemPitch = 0;
	vertexData.SysMemSlicePitch = 0;

	//Create the vertex buffer
	hresult = this->m_d3dHandler->GetDevice()->CreateBuffer(&vertexBufferDesc, &vertexData, &this->m_vertexBuffer);
	if (FAILED(hresult)) {
		return 1;
	}

	//Set up the description of the static index buffer
	ZeroMemory(&indexBufferDesc, sizeof(indexBufferDesc));
	indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
	indexBufferDesc.ByteWidth = sizeof(unsigned long) * sizeIndices;
	indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
	indexBufferDesc.CPUAccessFlags = 0;
	indexBufferDesc.MiscFlags = 0;
	indexBufferDesc.StructureByteStride = 0;

	ZeroMemory(&indexData, sizeof(indexData));
	indexData.pSysMem = &indices;
	indexData.SysMemPitch = 0;
	indexData.SysMemSlicePitch = 0;

	//Create the index buffer
	hresult = this->m_d3dHandler->GetDevice()->CreateBuffer(&indexBufferDesc, &indexData, &this->m_indexBuffer);
	if (FAILED(hresult)) {
		return 1;
	}

	return 0;
}

int GraphicsHandler::SetTriangle()
{
	unsigned int stride;
	unsigned offset;

	//Set vertex buffer stride and offset
	stride = sizeof(DirectX::XMFLOAT3);
	offset = 0;

	//Set the vertex buffer to active in the input assembly so it can rendered
	this->m_d3dHandler->GetDeviceContext()->IASetVertexBuffers(0, 1, &this->m_vertexBuffer, &stride, &offset);

	//Set the index buffer to active in the input assembler so it can be rendered
	this->m_d3dHandler->GetDeviceContext()->IASetIndexBuffer(this->m_indexBuffer, DXGI_FORMAT_R32_UINT, 0);

	//Set the type od primitiv that should be rendered from this vertex buffer, in this case triangles
	this->m_d3dHandler->GetDeviceContext()->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

	return 0;
}
<|endoftext|>


<commit_before>#include <QtGui>
#include <QtNetwork>

#include "account-mgr.h"
#include "seafile-applet.h"
#include "api/requests.h"
#include "login-dialog.h"

namespace {

const QString kDefaultServerAddr1 = "https://seacloud.cc";
const QString kDefaultServerAddr2 = "https://cloud.seafile.com";

} // namespace

LoginDialog::LoginDialog(QWidget *parent) : QDialog(parent)
{
    setupUi(this);
    setWindowTitle(tr("Add an account"));
    setWindowIcon(QIcon(":/images/seafile.png"));

    request_ = NULL;

    mStatusText->setText("");
    mLogo->setPixmap(QPixmap(":/images/seafile-32.png"));
    mServerAddr->addItem(kDefaultServerAddr1);
    mServerAddr->addItem(kDefaultServerAddr2);
    mServerAddr->clearEditText();

    connect(mSubmitBtn, SIGNAL(clicked()), this, SLOT(doLogin()));

    const QRect screen = QApplication::desktop()->screenGeometry();
    move(screen.center() - this->rect().center());
}

void LoginDialog::doLogin()
{
    if (!validateInputs()) {
        return;
    }
    mStatusText->setText(tr("Logging in..."));

    mServerAddr->setEnabled(false);
    mUsername->setEnabled(false);
    mPassword->setEnabled(false);
    mSubmitBtn->setEnabled(false);

    if (request_) {
        delete request_;
    }

    request_ = new LoginRequest(url_, username_, password_);
    request_->setIgnoreSslErrors(false);

    connect(request_, SIGNAL(success(const QString&)),
            this, SLOT(loginSuccess(const QString&)));

    connect(request_, SIGNAL(failed(int)),
            this, SLOT(loginFailed(int)));

    connect(request_, SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError>&)),
            this, SLOT(onSslErrors(QNetworkReply*, const QList<QSslError>&)));

    request_->send();
}

void LoginDialog::onSslErrors(QNetworkReply* reply, const QList<QSslError>& errors)
{
    QString question = tr("Warning: The ssl certificate of this server is not trusted, proceed anyway?");
    if (QMessageBox::question(this,
                              tr(SEAFILE_CLIENT_BRAND),
                              question,
                              QMessageBox::Yes | QMessageBox::No,
                              QMessageBox::No) == QMessageBox::Yes) {
        reply->ignoreSslErrors();
    }
}

bool LoginDialog::validateInputs()
{
    QString serverAddr = mServerAddr->itemText(mServerAddr->currentIndex());
    QString protocol;
    QUrl url;

    if (serverAddr.size() == 0) {
        QMessageBox::warning(this, tr(SEAFILE_CLIENT_BRAND),
                             tr("Please enter the server address"),
                             QMessageBox::Ok);
        return false;
    } else {
        if (!serverAddr.startsWith("http://") && !serverAddr.startsWith("https://")) {
            QMessageBox::warning(this, tr(SEAFILE_CLIENT_BRAND),
                                 tr("%1 is not a valid server address")
                                 .arg(serverAddr),
                                 QMessageBox::Ok);
            return false;
        }

        url = QUrl(serverAddr, QUrl::StrictMode);
        // qDebug("url is %s\n", url.toString().toUtf8().data());
        if (!url.isValid()) {
            QMessageBox::warning(this, tr(SEAFILE_CLIENT_BRAND),
                                 tr("%1 is not a valid server address")
                                 .arg(serverAddr),
                                 QMessageBox::Ok);
            return false;
        }
    }

    QString email = mUsername->text();
    if (email.size() == 0) {
        QMessageBox::warning(this, tr(SEAFILE_CLIENT_BRAND),
                             tr("Please enter the username"),
                             QMessageBox::Ok);
        return false;
    } else if (!email.contains("@")) {
        QMessageBox::warning(this, tr(SEAFILE_CLIENT_BRAND),
                             tr("%1 is not a valid email")
                             .arg(email),
                             QMessageBox::Ok);
        return false;
    }

    if (mPassword->text().size() == 0) {
        QMessageBox::warning(this, tr(SEAFILE_CLIENT_BRAND),
                             tr("Please enter the password"),
                             QMessageBox::Ok);
        return false;
    }

    url_ = url;
    username_ = mUsername->text();
    password_ = mPassword->text();

    return true;
}

void LoginDialog::loginSuccess(const QString& token)
{
    Account account(url_, username_, token);
    if (seafApplet->accountManager()->saveAccount(account) < 0) {
        QMessageBox::warning(this, tr(SEAFILE_CLIENT_BRAND),
                             tr("Internal Error"),
                             QMessageBox::Ok);
    } else {
        done(QDialog::Accepted);
    }
}

void LoginDialog::loginFailed(int code)
{
    QString err_msg, reason;
    if (code == 400) {
        reason = tr("Incorrect email or password");
    } else if (code != 0) {
        reason = tr("error code %1").arg(code);
    }

    if (reason.length() > 0) {
        err_msg = tr("Failed to login: %1").arg(reason);
    } else {
        err_msg = tr("Failed to login");
    }

    QMessageBox::warning(this, tr(SEAFILE_CLIENT_BRAND),
                         err_msg,
                         QMessageBox::Ok);

    mSubmitBtn->setEnabled(true);
    mServerAddr->setEnabled(true);
    mUsername->setEnabled(true);
    mPassword->setEnabled(true);

    mStatusText->setText("");
}
<commit_msg>fixed a bug in login dialog<commit_after>#include <QtGui>
#include <QtNetwork>

#include "account-mgr.h"
#include "seafile-applet.h"
#include "api/requests.h"
#include "login-dialog.h"

namespace {

const QString kDefaultServerAddr1 = "https://seacloud.cc";
const QString kDefaultServerAddr2 = "https://cloud.seafile.com";

} // namespace

LoginDialog::LoginDialog(QWidget *parent) : QDialog(parent)
{
    setupUi(this);
    setWindowTitle(tr("Add an account"));
    setWindowIcon(QIcon(":/images/seafile.png"));

    request_ = NULL;

    mStatusText->setText("");
    mLogo->setPixmap(QPixmap(":/images/seafile-32.png"));
    mServerAddr->addItem(kDefaultServerAddr1);
    mServerAddr->addItem(kDefaultServerAddr2);
    mServerAddr->clearEditText();

    connect(mSubmitBtn, SIGNAL(clicked()), this, SLOT(doLogin()));

    const QRect screen = QApplication::desktop()->screenGeometry();
    move(screen.center() - this->rect().center());
}

void LoginDialog::doLogin()
{
    if (!validateInputs()) {
        return;
    }
    mStatusText->setText(tr("Logging in..."));

    mServerAddr->setEnabled(false);
    mUsername->setEnabled(false);
    mPassword->setEnabled(false);
    mSubmitBtn->setEnabled(false);

    if (request_) {
        delete request_;
    }

    request_ = new LoginRequest(url_, username_, password_);
    request_->setIgnoreSslErrors(false);

    connect(request_, SIGNAL(success(const QString&)),
            this, SLOT(loginSuccess(const QString&)));

    connect(request_, SIGNAL(failed(int)),
            this, SLOT(loginFailed(int)));

    connect(request_, SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError>&)),
            this, SLOT(onSslErrors(QNetworkReply*, const QList<QSslError>&)));

    request_->send();
}

void LoginDialog::onSslErrors(QNetworkReply* reply, const QList<QSslError>& errors)
{
    QString question = tr("Warning: The ssl certificate of this server is not trusted, proceed anyway?");
    if (QMessageBox::question(this,
                              tr(SEAFILE_CLIENT_BRAND),
                              question,
                              QMessageBox::Yes | QMessageBox::No,
                              QMessageBox::No) == QMessageBox::Yes) {
        reply->ignoreSslErrors();
    }
}

bool LoginDialog::validateInputs()
{
    QString serverAddr = mServerAddr->currentText();
    QString protocol;
    QUrl url;

    if (serverAddr.size() == 0) {
        QMessageBox::warning(this, tr(SEAFILE_CLIENT_BRAND),
                             tr("Please enter the server address"),
                             QMessageBox::Ok);
        return false;
    } else {
        if (!serverAddr.startsWith("http://") && !serverAddr.startsWith("https://")) {
            QMessageBox::warning(this, tr(SEAFILE_CLIENT_BRAND),
                                 tr("%1 is not a valid server address")
                                 .arg(serverAddr),
                                 QMessageBox::Ok);
            return false;
        }

        url = QUrl(serverAddr, QUrl::StrictMode);
        // qDebug("url is %s\n", url.toString().toUtf8().data());
        if (!url.isValid()) {
            QMessageBox::warning(this, tr(SEAFILE_CLIENT_BRAND),
                                 tr("%1 is not a valid server address")
                                 .arg(serverAddr),
                                 QMessageBox::Ok);
            return false;
        }
    }

    QString email = mUsername->text();
    if (email.size() == 0) {
        QMessageBox::warning(this, tr(SEAFILE_CLIENT_BRAND),
                             tr("Please enter the username"),
                             QMessageBox::Ok);
        return false;
    } else if (!email.contains("@")) {
        QMessageBox::warning(this, tr(SEAFILE_CLIENT_BRAND),
                             tr("%1 is not a valid email")
                             .arg(email),
                             QMessageBox::Ok);
        return false;
    }

    if (mPassword->text().size() == 0) {
        QMessageBox::warning(this, tr(SEAFILE_CLIENT_BRAND),
                             tr("Please enter the password"),
                             QMessageBox::Ok);
        return false;
    }

    url_ = url;
    username_ = mUsername->text();
    password_ = mPassword->text();

    return true;
}

void LoginDialog::loginSuccess(const QString& token)
{
    Account account(url_, username_, token);
    if (seafApplet->accountManager()->saveAccount(account) < 0) {
        QMessageBox::warning(this, tr(SEAFILE_CLIENT_BRAND),
                             tr("Internal Error"),
                             QMessageBox::Ok);
    } else {
        done(QDialog::Accepted);
    }
}

void LoginDialog::loginFailed(int code)
{
    QString err_msg, reason;
    if (code == 400) {
        reason = tr("Incorrect email or password");
    } else if (code != 0) {
        reason = tr("error code %1").arg(code);
    }

    if (reason.length() > 0) {
        err_msg = tr("Failed to login: %1").arg(reason);
    } else {
        err_msg = tr("Failed to login");
    }

    QMessageBox::warning(this, tr(SEAFILE_CLIENT_BRAND),
                         err_msg,
                         QMessageBox::Ok);

    mSubmitBtn->setEnabled(true);
    mServerAddr->setEnabled(true);
    mUsername->setEnabled(true);
    mPassword->setEnabled(true);

    mStatusText->setText("");
}
<|endoftext|>


<commit_before>#include <QtGlobal>

#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
#include <QtWidgets>
#else
#include <QtGui>
#endif
#include <QtNetwork>
#include <QInputDialog>
#include <QStringList>
#include <QSettings>

#include "settings-mgr.h"
#include "account-mgr.h"
#include "seafile-applet.h"
#include "api/api-error.h"
#include "api/requests.h"
#include "login-dialog.h"
#include "utils/utils.h"
#ifdef HAVE_SHIBBOLETH_SUPPORT
#include "shib/shib-login-dialog.h"
#endif // HAVE_SHIBBOLETH_SUPPORT

namespace {

const char *kDefaultServerAddr1 = "https://seacloud.cc";
const char *kDefaultServerAddr2 = "https://cloud.seafile.de";
const char *kUsedServerAddresses = "UsedServerAddresses";
const char *const kPreconfigureServerAddr = "PreconfigureServerAddr";
const char *const kPreconfigureServerAddrOnly = "PreconfigureServerAddrOnly";

QStringList getUsedServerAddresses()
{
    QSettings settings;
    settings.beginGroup(kUsedServerAddresses);
    QStringList retval = settings.value("main").toStringList();
    settings.endGroup();
    QString preconfigure_addr = seafApplet->readPreconfigureExpandedString(kPreconfigureServerAddr);
    if (!preconfigure_addr.isEmpty() && !retval.contains(preconfigure_addr)) {
        retval.push_back(preconfigure_addr);
    }
    if (!retval.contains(kDefaultServerAddr1)) {
        retval.push_back(kDefaultServerAddr1);
    }
    if (!retval.contains(kDefaultServerAddr2)) {
        retval.push_back(kDefaultServerAddr2);
    }
    return retval;
}

void saveUsedServerAddresses(const QString &new_address)
{
    QSettings settings;
    settings.beginGroup(kUsedServerAddresses);
    QStringList list = settings.value("main").toStringList();
    // put the last used address to the front
    list.removeAll(new_address);
    list.insert(0, new_address);
    settings.setValue("main", list);
    settings.endGroup();
}

} // namespace

LoginDialog::LoginDialog(QWidget *parent) : QDialog(parent)
{
    setupUi(this);
    setWindowTitle(tr("Add an account"));
    setWindowIcon(QIcon(":/images/seafile.png"));
    setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);

    request_ = NULL;

    mStatusText->setText("");
    mLogo->setPixmap(QPixmap(":/images/seafile-32.png"));
    QString preconfigure_addr = seafApplet->readPreconfigureExpandedString(kPreconfigureServerAddr);
    if (seafApplet->readPreconfigureEntry(kPreconfigureServerAddrOnly).toBool() && !preconfigure_addr.isEmpty()) {
        mServerAddr->setMaxCount(1);
        mServerAddr->insertItem(0, preconfigure_addr);
        mServerAddr->setCurrentIndex(0);
        mServerAddr->setEditable(false);
    } else {
        mServerAddr->addItems(getUsedServerAddresses());
        mServerAddr->clearEditText();
    }
    mServerAddr->setAutoCompletion(false);

    QString computerName = seafApplet->settingsManager()->getComputerName();

    mComputerName->setText(computerName);

    connect(mSubmitBtn, SIGNAL(clicked()), this, SLOT(doLogin()));

    const QRect screen = QApplication::desktop()->screenGeometry();
    move(screen.center() - this->rect().center());

#ifdef HAVE_SHIBBOLETH_SUPPORT
    setupShibLoginLink();
#else
    mShibLoginLink->hide();
#endif
}

#ifdef HAVE_SHIBBOLETH_SUPPORT
void LoginDialog::setupShibLoginLink()
{
    QString txt = QString("%1").arg(tr("Shibboleth Login"));
    mShibLoginLink->setText(txt);
    connect(mShibLoginLink, SIGNAL(linkActivated(const QString&)),
            this, SLOT(loginWithShib()));
}
#endif // HAVE_SHIBBOLETH_SUPPORT

void LoginDialog::initFromAccount(const Account& account)
{
    setWindowTitle(tr("Re-login"));
    mTitle->setText(tr("Re-login"));
    mServerAddr->setMaxCount(1);
    mServerAddr->insertItem(0, account.serverUrl.toString());
    mServerAddr->setCurrentIndex(0);
    mServerAddr->setEditable(false);

    mUsername->setText(account.username);
    mPassword->setFocus(Qt::OtherFocusReason);
}

void LoginDialog::doLogin()
{
    if (!validateInputs()) {
        return;
    }
    mStatusText->setText(tr("Logging in..."));

    disableInputs();

    if (request_) {
        delete request_;
    }

    request_ = new LoginRequest(url_, username_, password_, computer_name_);
    request_->setIgnoreSslErrors(false);

    connect(request_, SIGNAL(success(const QString&)),
            this, SLOT(loginSuccess(const QString&)));

    connect(request_, SIGNAL(failed(const ApiError&)),
            this, SLOT(loginFailed(const ApiError&)));

    request_->send();
}

void LoginDialog::disableInputs()
{
    mServerAddr->setEnabled(false);
    mUsername->setEnabled(false);
    mPassword->setEnabled(false);
    mSubmitBtn->setEnabled(false);
    mComputerName->setEnabled(false);
}

void LoginDialog::enableInputs()
{
    mServerAddr->setEnabled(true);
    mUsername->setEnabled(true);
    mPassword->setEnabled(true);
    mSubmitBtn->setEnabled(true);
    mComputerName->setEnabled(true);
}

void LoginDialog::onNetworkError(const QNetworkReply::NetworkError& error, const QString& error_string)
{
    showWarning(tr("Network Error:\n %1").arg(error_string));
    enableInputs();

    mStatusText->setText("");
}

void LoginDialog::onSslErrors(QNetworkReply* reply, const QList<QSslError>& errors)
{
    const QSslCertificate &cert = reply->sslConfiguration().peerCertificate();
    qDebug() << "\n= SslErrors =\n" << dumpSslErrors(errors);
    qDebug() << "\n= Certificate =\n" << dumpCertificate(cert);

    if (seafApplet->detailedYesOrNoBox(tr("Warning: The ssl certificate of this server is not trusted, proceed anyway?"),
                                   dumpSslErrors(errors) + dumpCertificate(cert),
                                   this,
                                   false))
        reply->ignoreSslErrors();
}

bool LoginDialog::validateInputs()
{
    QString serverAddr = mServerAddr->currentText();
    QString protocol;
    QUrl url;

    if (serverAddr.size() == 0) {
        showWarning(tr("Please enter the server address"));
        return false;
    } else {
        if (!serverAddr.startsWith("http://") && !serverAddr.startsWith("https://")) {
            showWarning(tr("%1 is not a valid server address").arg(serverAddr));
            return false;
        }

        url = QUrl(serverAddr, QUrl::StrictMode);
        if (!url.isValid()) {
            showWarning(tr("%1 is not a valid server address").arg(serverAddr));
            return false;
        }
    }

    QString email = mUsername->text();
    if (email.size() == 0) {
        showWarning(tr("Please enter the username"));
        return false;
    }

    if (mPassword->text().size() == 0) {
        showWarning(tr("Please enter the password"));
        return false;
    }

    QString computer_name = mComputerName->text().trimmed();
    if (computer_name.size() == 0) {
        showWarning(tr("Please enter the computer name"));
    }

    url_ = url;
    username_ = mUsername->text();
    password_ = mPassword->text();
    computer_name_ = mComputerName->text();

    seafApplet->settingsManager()->setComputerName(computer_name_);

    return true;
}

void LoginDialog::loginSuccess(const QString& token)
{
    Account account(url_, username_, token);
    saveUsedServerAddresses(url_.toString());
    if (seafApplet->accountManager()->saveAccount(account) < 0) {
        showWarning(tr("Failed to save current account"));
    } else {
        done(QDialog::Accepted);
    }
}

void LoginDialog::loginFailed(const ApiError& error)
{
    switch (error.type()) {
    case ApiError::SSL_ERROR:
        onSslErrors(error.sslReply(), error.sslErrors());
        break;
    case ApiError::NETWORK_ERROR:
        onNetworkError(error.networkError(), error.networkErrorString());
        break;
    case ApiError::HTTP_ERROR:
        onHttpError(error.httpErrorCode());
    default:
        // impossible
        break;
    }
}

void LoginDialog::onHttpError(int code)
{
    QString err_msg, reason;
    if (code == 400) {
        reason = tr("Incorrect email or password");
    } else if (code == 429) {
        reason = tr("Logging in too frequently, please wait a minute");
    } else if (code == 500) {
        reason = tr("Internal Server Error");
    }

    if (reason.length() > 0) {
        err_msg = tr("Failed to login: %1").arg(reason);
    } else {
        err_msg = tr("Failed to login");
    }

    showWarning(err_msg);

    enableInputs();

    mStatusText->setText("");
}

void LoginDialog::showWarning(const QString& msg)
{
    seafApplet->warningBox(msg, this);
}

#ifdef HAVE_SHIBBOLETH_SUPPORT
void LoginDialog::loginWithShib()
{
    QString serverAddr = seafApplet->settingsManager()->getLastShibUrl();
    serverAddr = QInputDialog::getText(this, tr("Shibboleth Login"),
                                       tr("Seafile Server Address"),
                                       QLineEdit::Normal,
                                       serverAddr);
    serverAddr = serverAddr.trimmed();
    if (serverAddr.isEmpty()) {
        return;
    }

    if (!serverAddr.startsWith("http://") && !serverAddr.startsWith("https://")) {
        showWarning(tr("%1 is not a valid server address").arg(serverAddr));
        return;
    }

    QUrl url = QUrl(serverAddr, QUrl::StrictMode);
    if (!url.isValid()) {
        showWarning(tr("%1 is not a valid server address").arg(serverAddr));
        return;
    }

    seafApplet->settingsManager()->setLastShibUrl(serverAddr);

    ShibLoginDialog shib_dialog(url, mComputerName->text(), this);
    if (shib_dialog.exec() == QDialog::Accepted) {
        accept();
    }
}
#endif // HAVE_SHIBBOLETH_SUPPORT
<commit_msg>update builtin servers lists<commit_after>#include <QtGlobal>

#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
#include <QtWidgets>
#else
#include <QtGui>
#endif
#include <QtNetwork>
#include <QInputDialog>
#include <QStringList>
#include <QSettings>

#include "settings-mgr.h"
#include "account-mgr.h"
#include "seafile-applet.h"
#include "api/api-error.h"
#include "api/requests.h"
#include "login-dialog.h"
#include "utils/utils.h"
#ifdef HAVE_SHIBBOLETH_SUPPORT
#include "shib/shib-login-dialog.h"
#endif // HAVE_SHIBBOLETH_SUPPORT

namespace {

const char *kDefaultServerAddr1 = "https://seacloud.cc";
const char *kDefaultServerAddr2 = "https://app.seafile.de";
const char *kUsedServerAddresses = "UsedServerAddresses";
const char *const kPreconfigureServerAddr = "PreconfigureServerAddr";
const char *const kPreconfigureServerAddrOnly = "PreconfigureServerAddrOnly";

QStringList getUsedServerAddresses()
{
    QSettings settings;
    settings.beginGroup(kUsedServerAddresses);
    QStringList retval = settings.value("main").toStringList();
    settings.endGroup();
    QString preconfigure_addr = seafApplet->readPreconfigureExpandedString(kPreconfigureServerAddr);
    if (!preconfigure_addr.isEmpty() && !retval.contains(preconfigure_addr)) {
        retval.push_back(preconfigure_addr);
    }
    if (!retval.contains(kDefaultServerAddr1)) {
        retval.push_back(kDefaultServerAddr1);
    }
    if (!retval.contains(kDefaultServerAddr2)) {
        retval.push_back(kDefaultServerAddr2);
    }
    return retval;
}

void saveUsedServerAddresses(const QString &new_address)
{
    QSettings settings;
    settings.beginGroup(kUsedServerAddresses);
    QStringList list = settings.value("main").toStringList();
    // put the last used address to the front
    list.removeAll(new_address);
    list.insert(0, new_address);
    settings.setValue("main", list);
    settings.endGroup();
}

} // namespace

LoginDialog::LoginDialog(QWidget *parent) : QDialog(parent)
{
    setupUi(this);
    setWindowTitle(tr("Add an account"));
    setWindowIcon(QIcon(":/images/seafile.png"));
    setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);

    request_ = NULL;

    mStatusText->setText("");
    mLogo->setPixmap(QPixmap(":/images/seafile-32.png"));
    QString preconfigure_addr = seafApplet->readPreconfigureExpandedString(kPreconfigureServerAddr);
    if (seafApplet->readPreconfigureEntry(kPreconfigureServerAddrOnly).toBool() && !preconfigure_addr.isEmpty()) {
        mServerAddr->setMaxCount(1);
        mServerAddr->insertItem(0, preconfigure_addr);
        mServerAddr->setCurrentIndex(0);
        mServerAddr->setEditable(false);
    } else {
        mServerAddr->addItems(getUsedServerAddresses());
        mServerAddr->clearEditText();
    }
    mServerAddr->setAutoCompletion(false);

    QString computerName = seafApplet->settingsManager()->getComputerName();

    mComputerName->setText(computerName);

    connect(mSubmitBtn, SIGNAL(clicked()), this, SLOT(doLogin()));

    const QRect screen = QApplication::desktop()->screenGeometry();
    move(screen.center() - this->rect().center());

#ifdef HAVE_SHIBBOLETH_SUPPORT
    setupShibLoginLink();
#else
    mShibLoginLink->hide();
#endif
}

#ifdef HAVE_SHIBBOLETH_SUPPORT
void LoginDialog::setupShibLoginLink()
{
    QString txt = QString("%1").arg(tr("Shibboleth Login"));
    mShibLoginLink->setText(txt);
    connect(mShibLoginLink, SIGNAL(linkActivated(const QString&)),
            this, SLOT(loginWithShib()));
}
#endif // HAVE_SHIBBOLETH_SUPPORT

void LoginDialog::initFromAccount(const Account& account)
{
    setWindowTitle(tr("Re-login"));
    mTitle->setText(tr("Re-login"));
    mServerAddr->setMaxCount(1);
    mServerAddr->insertItem(0, account.serverUrl.toString());
    mServerAddr->setCurrentIndex(0);
    mServerAddr->setEditable(false);

    mUsername->setText(account.username);
    mPassword->setFocus(Qt::OtherFocusReason);
}

void LoginDialog::doLogin()
{
    if (!validateInputs()) {
        return;
    }
    mStatusText->setText(tr("Logging in..."));

    disableInputs();

    if (request_) {
        delete request_;
    }

    request_ = new LoginRequest(url_, username_, password_, computer_name_);
    request_->setIgnoreSslErrors(false);

    connect(request_, SIGNAL(success(const QString&)),
            this, SLOT(loginSuccess(const QString&)));

    connect(request_, SIGNAL(failed(const ApiError&)),
            this, SLOT(loginFailed(const ApiError&)));

    request_->send();
}

void LoginDialog::disableInputs()
{
    mServerAddr->setEnabled(false);
    mUsername->setEnabled(false);
    mPassword->setEnabled(false);
    mSubmitBtn->setEnabled(false);
    mComputerName->setEnabled(false);
}

void LoginDialog::enableInputs()
{
    mServerAddr->setEnabled(true);
    mUsername->setEnabled(true);
    mPassword->setEnabled(true);
    mSubmitBtn->setEnabled(true);
    mComputerName->setEnabled(true);
}

void LoginDialog::onNetworkError(const QNetworkReply::NetworkError& error, const QString& error_string)
{
    showWarning(tr("Network Error:\n %1").arg(error_string));
    enableInputs();

    mStatusText->setText("");
}

void LoginDialog::onSslErrors(QNetworkReply* reply, const QList<QSslError>& errors)
{
    const QSslCertificate &cert = reply->sslConfiguration().peerCertificate();
    qDebug() << "\n= SslErrors =\n" << dumpSslErrors(errors);
    qDebug() << "\n= Certificate =\n" << dumpCertificate(cert);

    if (seafApplet->detailedYesOrNoBox(tr("Warning: The ssl certificate of this server is not trusted, proceed anyway?"),
                                   dumpSslErrors(errors) + dumpCertificate(cert),
                                   this,
                                   false))
        reply->ignoreSslErrors();
}

bool LoginDialog::validateInputs()
{
    QString serverAddr = mServerAddr->currentText();
    QString protocol;
    QUrl url;

    if (serverAddr.size() == 0) {
        showWarning(tr("Please enter the server address"));
        return false;
    } else {
        if (!serverAddr.startsWith("http://") && !serverAddr.startsWith("https://")) {
            showWarning(tr("%1 is not a valid server address").arg(serverAddr));
            return false;
        }

        url = QUrl(serverAddr, QUrl::StrictMode);
        if (!url.isValid()) {
            showWarning(tr("%1 is not a valid server address").arg(serverAddr));
            return false;
        }
    }

    QString email = mUsername->text();
    if (email.size() == 0) {
        showWarning(tr("Please enter the username"));
        return false;
    }

    if (mPassword->text().size() == 0) {
        showWarning(tr("Please enter the password"));
        return false;
    }

    QString computer_name = mComputerName->text().trimmed();
    if (computer_name.size() == 0) {
        showWarning(tr("Please enter the computer name"));
    }

    url_ = url;
    username_ = mUsername->text();
    password_ = mPassword->text();
    computer_name_ = mComputerName->text();

    seafApplet->settingsManager()->setComputerName(computer_name_);

    return true;
}

void LoginDialog::loginSuccess(const QString& token)
{
    Account account(url_, username_, token);
    saveUsedServerAddresses(url_.toString());
    if (seafApplet->accountManager()->saveAccount(account) < 0) {
        showWarning(tr("Failed to save current account"));
    } else {
        done(QDialog::Accepted);
    }
}

void LoginDialog::loginFailed(const ApiError& error)
{
    switch (error.type()) {
    case ApiError::SSL_ERROR:
        onSslErrors(error.sslReply(), error.sslErrors());
        break;
    case ApiError::NETWORK_ERROR:
        onNetworkError(error.networkError(), error.networkErrorString());
        break;
    case ApiError::HTTP_ERROR:
        onHttpError(error.httpErrorCode());
    default:
        // impossible
        break;
    }
}

void LoginDialog::onHttpError(int code)
{
    QString err_msg, reason;
    if (code == 400) {
        reason = tr("Incorrect email or password");
    } else if (code == 429) {
        reason = tr("Logging in too frequently, please wait a minute");
    } else if (code == 500) {
        reason = tr("Internal Server Error");
    }

    if (reason.length() > 0) {
        err_msg = tr("Failed to login: %1").arg(reason);
    } else {
        err_msg = tr("Failed to login");
    }

    showWarning(err_msg);

    enableInputs();

    mStatusText->setText("");
}

void LoginDialog::showWarning(const QString& msg)
{
    seafApplet->warningBox(msg, this);
}

#ifdef HAVE_SHIBBOLETH_SUPPORT
void LoginDialog::loginWithShib()
{
    QString serverAddr = seafApplet->settingsManager()->getLastShibUrl();
    serverAddr = QInputDialog::getText(this, tr("Shibboleth Login"),
                                       tr("Seafile Server Address"),
                                       QLineEdit::Normal,
                                       serverAddr);
    serverAddr = serverAddr.trimmed();
    if (serverAddr.isEmpty()) {
        return;
    }

    if (!serverAddr.startsWith("http://") && !serverAddr.startsWith("https://")) {
        showWarning(tr("%1 is not a valid server address").arg(serverAddr));
        return;
    }

    QUrl url = QUrl(serverAddr, QUrl::StrictMode);
    if (!url.isValid()) {
        showWarning(tr("%1 is not a valid server address").arg(serverAddr));
        return;
    }

    seafApplet->settingsManager()->setLastShibUrl(serverAddr);

    ShibLoginDialog shib_dialog(url, mComputerName->text(), this);
    if (shib_dialog.exec() == QDialog::Accepted) {
        accept();
    }
}
#endif // HAVE_SHIBBOLETH_SUPPORT
<|endoftext|>


<commit_before>//-----------------------------------------------
//
//	This file is part of the Siv3D Engine.
//
//	Copyright (C) 2008-2017 Ryo Suzuki
//	Copyright (C) 2016-2017 OpenSiv3D Project
//
//	Licensed under the MIT License.
//
//-----------------------------------------------

# include <Siv3D/Platform.hpp>
# if defined(SIV3D_TARGET_MACOS)

# include "CWindow_macOS.hpp"

namespace s3d
{
	CWindow_macOS::CWindow_macOS()
	{

	}

	CWindow_macOS::~CWindow_macOS()
	{
		glfwTerminate();
	}

	bool CWindow_macOS::init()
	{
		if (!glfwInit())
		{
			return false;
		}

		m_glfwWindow = glfwCreateWindow(Window::DefaultClientSize.x, Window::DefaultClientSize.y, m_currentTitle.narrow().c_str(), nullptr, nullptr);

		if (!m_glfwWindow)
		{
			glfwTerminate();

			return false;
		}

		glfwMakeContextCurrent(m_glfwWindow);

		return true;
	}

	bool CWindow_macOS::update()
	{
		glClearColor(11/255.0f, 22/255.0f, 33/255.0f, 1.0f);

		glClear(GL_COLOR_BUFFER_BIT);

		glfwSwapBuffers(m_glfwWindow);

		glfwPollEvents();

		if(glfwGetKey(m_glfwWindow, GLFW_KEY_ESCAPE) == GLFW_PRESS)
		{
			glfwSetWindowShouldClose(m_glfwWindow, GL_TRUE);
		}

		if(glfwWindowShouldClose(m_glfwWindow))
		{
			return false;
		}

		return true;
	}

	WindowHandle CWindow_macOS::getHandle() const
	{
		return m_glfwWindow;
	}

	void CWindow_macOS::setTitle(const String& title)
	{
		if (title == m_currentTitle)
		{
			return;
		}

		m_currentTitle = title;

		glfwSetWindowTitle(m_glfwWindow, m_currentTitle.narrow().c_str());
	}
}

# endif
<commit_msg>window size fixed<commit_after>//-----------------------------------------------
//
//	This file is part of the Siv3D Engine.
//
//	Copyright (C) 2008-2017 Ryo Suzuki
//	Copyright (C) 2016-2017 OpenSiv3D Project
//
//	Licensed under the MIT License.
//
//-----------------------------------------------

# include <Siv3D/Platform.hpp>
# if defined(SIV3D_TARGET_MACOS)

# include "CWindow_macOS.hpp"

namespace s3d
{
	CWindow_macOS::CWindow_macOS()
	{

	}

	CWindow_macOS::~CWindow_macOS()
	{
		glfwTerminate();
	}

	bool CWindow_macOS::init()
	{
		if (!glfwInit())
		{
			return false;
		}

		glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

		m_glfwWindow = glfwCreateWindow(Window::DefaultClientSize.x, Window::DefaultClientSize.y, m_currentTitle.narrow().c_str(), nullptr, nullptr);

		if (!m_glfwWindow)
		{
			glfwTerminate();

			return false;
		}

		glfwMakeContextCurrent(m_glfwWindow);

		return true;
	}

	bool CWindow_macOS::update()
	{
		glClearColor(11/255.0f, 22/255.0f, 33/255.0f, 1.0f);

		glClear(GL_COLOR_BUFFER_BIT);

		glfwSwapBuffers(m_glfwWindow);

		glfwPollEvents();

		if(glfwGetKey(m_glfwWindow, GLFW_KEY_ESCAPE) == GLFW_PRESS)
		{
			glfwSetWindowShouldClose(m_glfwWindow, GL_TRUE);
		}

		if(glfwWindowShouldClose(m_glfwWindow))
		{
			return false;
		}

		return true;
	}

	WindowHandle CWindow_macOS::getHandle() const
	{
		return m_glfwWindow;
	}

	void CWindow_macOS::setTitle(const String& title)
	{
		if (title == m_currentTitle)
		{
			return;
		}

		m_currentTitle = title;

		glfwSetWindowTitle(m_glfwWindow, m_currentTitle.narrow().c_str());
	}
}

# endif
<|endoftext|>