<commit_before>#include "cssysdef.h"
#include "aws/awslabel.h"
#include "ivideo/graph2d.h"
#include "ivideo/graph3d.h"
#include "ivideo/fontserv.h"
#include "csutil/scfstr.h"

#include <stdio.h>

SCF_IMPLEMENT_IBASE(awsLabel)
  SCF_IMPLEMENTS_INTERFACE(awsComponent)
SCF_IMPLEMENT_IBASE_END

const int awsLabel::signalClicked=0x1;

awsLabel::awsLabel():is_down(false), mouse_is_over(false),
                     caption(NULL)
{ }

awsLabel::~awsLabel()
{ }

char *
awsLabel::Type()
{ return "Label"; }

bool
awsLabel::Setup(iAws *_wmgr, awsComponentNode *settings)
{
 if (!awsComponent::Setup(_wmgr, settings)) return false;

 iAwsPrefManager *pm=WindowManager()->GetPrefMgr();

 pm->GetString(settings, "Caption", caption);

 return true;
}

bool
awsLabel::GetProperty(char *name, void **parm)
{
  if (awsComponent::GetProperty(name, parm)) return true;

  if (strcmp("Caption", name)==0)
  {
    char *st = NULL;

    if (caption) st=caption->GetData();

    iString *s = new scfString(st);
    *parm = (void *)s;
    return true;
  }

  return false;
}

bool
awsLabel::SetProperty(char *name, void *parm)
{
  if (awsComponent::SetProperty(name, parm)) return true;

  if (strcmp("Caption", name)==0)
  {
    iString *s = (iString *)(parm);

    if (s)
    {
      if (caption) caption->DecRef();
      caption=s;
      caption->IncRef();
      Invalidate();
    }

    return true;
  }

  return false;
}

void
awsLabel::OnDraw(csRect clip)
{
  iGraphics2D *g2d = WindowManager()->G2D();

   // Draw the caption, if there is one
   if (caption)
    {
      int tw, th, tx, ty;

      // Get the size of the text
      WindowManager()->GetPrefMgr()->GetDefaultFont()->GetDimensions(caption->GetData(), tw, th);

      // Calculate the center
      tx = (Frame().Width()>>1) -  (tw>>1);
      ty = (Frame().Height()>>1) - (th>>1);

      // Draw the text
      g2d->Write(WindowManager()->GetPrefMgr()->GetDefaultFont(),
                 Frame().xmin+tx+is_down,
                 Frame().ymin+ty+is_down,
                 WindowManager()->GetPrefMgr()->GetColor(AC_TEXTFORE),
                 -1,
                 caption->GetData());

    }
}

bool
awsLabel::OnMouseDown(int button, int x, int y)
{
  is_down=true;
  //Invalidate();
  return false;
}

bool
awsLabel::OnMouseUp(int button, int x, int y)
{
  if (is_down)
    Broadcast(signalClicked);

  is_down=false;
  //Invalidate();
  return false;
}

bool
awsLabel::OnMouseMove(int button, int x, int y)
{
  return false;
}

bool
awsLabel::OnMouseClick(int button, int x, int y)
{
  return false;
}

bool
awsLabel::OnMouseDoubleClick(int button, int x, int y)
{
  return false;
}

bool
awsLabel::OnMouseExit()
{
  mouse_is_over=false;
  //Invalidate();

  if (is_down)
    is_down=false;

  return true;
}

bool
awsLabel::OnMouseEnter()
{
  mouse_is_over=true;
  //Invalidate();
  return true;
}

bool
awsLabel::OnKeypress(int key, int modifiers)
{
  return false;
}

bool
awsLabel::OnLostFocus()
{
  return false;
}

bool
awsLabel::OnGainFocus()
{
  return false;
}

/************************************* Command Button Factory ****************/
SCF_IMPLEMENT_IBASE(awsLabelFactory)
  SCF_IMPLEMENTS_INTERFACE(iAwsComponentFactory)
SCF_IMPLEMENT_IBASE_END

awsLabelFactory::awsLabelFactory(iAws *wmgr):awsComponentFactory(wmgr)
{
  Register("Label");
  RegisterConstant("signalLabelClicked",  awsLabel::signalClicked);
}

awsLabelFactory::~awsLabelFactory()
{
 // empty
}

iAwsComponent *
awsLabelFactory::Create()
{
 return new awsLabel;
}

<commit_msg>Christopher:<commit_after>#include "cssysdef.h"
#include "aws/awslabel.h"
#include "ivideo/graph2d.h"
#include "ivideo/graph3d.h"
#include "ivideo/fontserv.h"
#include "csutil/scfstr.h"

#include <stdio.h>

SCF_IMPLEMENT_IBASE(awsLabel)
  SCF_IMPLEMENTS_INTERFACE(awsComponent)
SCF_IMPLEMENT_IBASE_END

const int awsLabel::signalClicked=0x1;

const int awsLabel::alignLeft=0x0;
const int awsLabel::alignRight=0x1;
const int awsLabel::alignCenter=0x2;

awsLabel::awsLabel():is_down(false), mouse_is_over(false), alignment(0),
                     caption(NULL)
{ }

awsLabel::~awsLabel()
{ }

char *
awsLabel::Type()
{ return "Label"; }

bool
awsLabel::Setup(iAws *_wmgr, awsComponentNode *settings)
{
 if (!awsComponent::Setup(_wmgr, settings)) return false;

 iAwsPrefManager *pm=WindowManager()->GetPrefMgr();

 pm->GetString(settings, "Caption", caption);
 pm->GetInt(settings, "Align", alignment);

 return true;
}

bool
awsLabel::GetProperty(char *name, void **parm)
{
  if (awsComponent::GetProperty(name, parm)) return true;

  if (strcmp("Caption", name)==0)
  {
    char *st = NULL;

    if (caption) st=caption->GetData();

    iString *s = new scfString(st);
    *parm = (void *)s;
    return true;
  }

  return false;
}

bool
awsLabel::SetProperty(char *name, void *parm)
{
  if (awsComponent::SetProperty(name, parm)) return true;

  if (strcmp("Caption", name)==0)
  {
    iString *s = (iString *)(parm);

    if (s)
    {
      if (caption) caption->DecRef();
      caption=s;
      caption->IncRef();
      Invalidate();
    }

    return true;
  }

  return false;
}

void
awsLabel::OnDraw(csRect clip)
{
  iGraphics2D *g2d = WindowManager()->G2D();

   // Draw the caption, if there is one
   if (caption)
    {
      int tw, th, tx, ty, mcc;

      mcc = WindowManager()->GetPrefMgr()->GetDefaultFont()->GetLength(caption->GetData(), Frame().Width());

      scfString tmp(caption->GetData());
      tmp.Truncate(mcc);

      // Get the size of the text
      WindowManager()->GetPrefMgr()->GetDefaultFont()->GetDimensions(tmp.GetData(), tw, th);

      // Calculate the center
      ty = (Frame().Height()>>1) - (th>>1);

      switch(alignment)
      {
      case alignRight:
        tx = Frame().Width()-tw;
        break;

      case alignCenter:
        tx = (Frame().Width()>>1) -  (tw>>1);
        break;

      default:
        tx = 0;
        break;
      }

      // Draw the text
      g2d->Write(WindowManager()->GetPrefMgr()->GetDefaultFont(),
                 Frame().xmin+tx+is_down,
                 Frame().ymin+ty+is_down,
                 WindowManager()->GetPrefMgr()->GetColor(AC_TEXTFORE),
                 -1,
                 tmp.GetData());

    }
}

bool
awsLabel::OnMouseDown(int button, int x, int y)
{
  is_down=true;
  //Invalidate();
  return false;
}

bool
awsLabel::OnMouseUp(int button, int x, int y)
{
  if (is_down)
    Broadcast(signalClicked);

  is_down=false;
  //Invalidate();
  return false;
}

bool
awsLabel::OnMouseMove(int button, int x, int y)
{
  return false;
}

bool
awsLabel::OnMouseClick(int button, int x, int y)
{
  return false;
}

bool
awsLabel::OnMouseDoubleClick(int button, int x, int y)
{
  return false;
}

bool
awsLabel::OnMouseExit()
{
  mouse_is_over=false;
  //Invalidate();

  if (is_down)
    is_down=false;

  return true;
}

bool
awsLabel::OnMouseEnter()
{
  mouse_is_over=true;
  //Invalidate();
  return true;
}

bool
awsLabel::OnKeypress(int key, int modifiers)
{
  return false;
}

bool
awsLabel::OnLostFocus()
{
  return false;
}

bool
awsLabel::OnGainFocus()
{
  return false;
}

/************************************* Command Button Factory ****************/
SCF_IMPLEMENT_IBASE(awsLabelFactory)
  SCF_IMPLEMENTS_INTERFACE(iAwsComponentFactory)
SCF_IMPLEMENT_IBASE_END

awsLabelFactory::awsLabelFactory(iAws *wmgr):awsComponentFactory(wmgr)
{
  Register("Label");
  RegisterConstant("signalLabelClicked",  awsLabel::signalClicked);

  RegisterConstant("lblAlignLeft",  awsLabel::alignLeft);
  RegisterConstant("lblAlignRight",  awsLabel::alignRight);
  RegisterConstant("lblAlignCenter",  awsLabel::alignCenter);
}

awsLabelFactory::~awsLabelFactory()
{
 // empty
}

iAwsComponent *
awsLabelFactory::Create()
{
 return new awsLabel;
}

<|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Need to include this before any other file because it defines
// IPC_MESSAGE_LOG_ENABLED. We need to use it to define
// IPC_MESSAGE_MACROS_LOG_ENABLED so that all_messages.h will generate the
// ViewMsgLog et al. functions.
#include "ipc/ipc_message.h"

#ifdef IPC_MESSAGE_LOG_ENABLED
#define IPC_MESSAGE_MACROS_LOG_ENABLED

// We need to do this real early to be sure IPC_MESSAGE_MACROS_LOG_ENABLED
// doesn't get undefined.
#include "chrome/common/all_messages.h"

#include "chrome/browser/ui/views/about_ipc_dialog.h"

#include <set>

#include "base/string_util.h"
#include "base/threading/thread.h"
#include "base/time.h"
#include "base/utf_string_conversions.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/ui/browser_dialogs.h"
#include "chrome/common/chrome_constants.h"
#include "content/public/browser/content_ipc_logging.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_job.h"
#include "ui/views/controls/button/text_button.h"
#include "ui/views/controls/native/native_view_host.h"
#include "ui/views/layout/grid_layout.h"
#include "ui/views/layout/layout_constants.h"
#include "ui/views/widget/widget.h"

namespace {

// We don't localize this UI since this is a developer-only feature.
const wchar_t kStartTrackingLabel[] = L"Start tracking";
const wchar_t kStopTrackingLabel[] = L"Stop tracking";
const wchar_t kClearLabel[] = L"Clear";
const wchar_t kFilterLabel[] = L"Filter...";

enum {
  kTimeColumn = 0,
  kChannelColumn,
  kMessageColumn,
  kFlagsColumn,
  kDispatchColumn,
  kProcessColumn,
  kParamsColumn,
};

// This class registers the browser IPC logger functions with IPC::Logging.
class RegisterLoggerFuncs {
 public:
  RegisterLoggerFuncs() {
    IPC::Logging::set_log_function_map(&g_log_function_mapping);
  }
};

RegisterLoggerFuncs g_register_logger_funcs;

// The singleton dialog box. This is non-NULL when a dialog is active so we
// know not to create a new one.
AboutIPCDialog* g_active_dialog = NULL;

std::set<int> disabled_messages;

// Settings dialog -------------------------------------------------------------

bool init_done = false;
HWND settings_dialog = NULL;
// Settings.
CListViewCtrl* messages = NULL;

void OnCheck(int id, bool checked) {
  if (!init_done)
    return;

  if (checked)
    disabled_messages.erase(id);
  else
    disabled_messages.insert(id);
}

void InitDialog(HWND hwnd) {
  messages = new CListViewCtrl(::GetDlgItem(hwnd, IDC_Messages));

  messages->SetViewType(LVS_REPORT);
  messages->SetExtendedListViewStyle(LVS_EX_CHECKBOXES);
  messages->ModifyStyle(0, LVS_SORTASCENDING | LVS_NOCOLUMNHEADER);
  messages->InsertColumn(0, L"id", LVCFMT_LEFT, 230);

  LogFunctionMap* log_functions = IPC::Logging::log_function_map();
  for (LogFunctionMap::iterator i = log_functions->begin();
       i != log_functions->end(); ++i) {
    std::string name;
    (*i->second)(&name, NULL, NULL);
    if (name.empty())
      continue;  // Will happen if the message file isn't included above.
    std::wstring wname = UTF8ToWide(name);

    int index = messages->InsertItem(
        LVIF_TEXT | LVIF_PARAM, 0, wname.c_str(), 0, 0, 0, i->first);

    messages->SetItemText(index, 0, wname.c_str());

    if (disabled_messages.find(i->first) == disabled_messages.end())
      messages->SetCheckState(index, TRUE);
  }

  init_done = true;
}

void CloseDialog() {
  delete messages;
  messages = NULL;

  init_done = false;

  ::DestroyWindow(settings_dialog);
  settings_dialog = NULL;

  /* The old version of this code stored the last settings in the preferences.
     But with this dialog, there currently isn't an easy way to get the profile
     to save in the preferences.
  Profile* current_profile = profile();
  if (!current_profile)
    return;
  PrefService* prefs = current_profile->GetPrefs();
  if (!prefs->FindPreference(prefs::kIpcDisabledMessages))
    return;
  ListValue* list = prefs->GetMutableList(prefs::kIpcDisabledMessages);
  list->Clear();
  for (std::set<int>::const_iterator itr = disabled_messages_.begin();
       itr != disabled_messages_.end();
       ++itr) {
    list->Append(Value::CreateIntegerValue(*itr));
  }
  */
}

void OnButtonClick(int id) {
  int count = messages->GetItemCount();
  for (int i = 0; i < count; ++i)
    messages->SetCheckState(i, id == IDC_MessagesAll);
}

INT_PTR CALLBACK DialogProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
  switch (msg) {
    case WM_INITDIALOG:
      InitDialog(hwnd);
      return FALSE;  // Don't set keyboard focus.
    case WM_SYSCOMMAND:
      if (wparam == SC_CLOSE) {
        CloseDialog();
        return FALSE;
      }
      break;
    case WM_NOTIFY: {
      NMLISTVIEW* info = reinterpret_cast<NM_LISTVIEW*>(lparam);
      if (wparam == IDC_Messages && info->hdr.code == LVN_ITEMCHANGED) {
        if (info->uChanged & LVIF_STATE) {
          bool checked = (info->uNewState >> 12) == 2;
          OnCheck(static_cast<int>(info->lParam), checked);
        }
        return FALSE;
      }
      break;
    }
    case WM_COMMAND:
      if (HIWORD(wparam) == BN_CLICKED)
        OnButtonClick(LOWORD(wparam));
      break;
  }
  return FALSE;
}

void RunSettingsDialog(HWND parent) {
  if (settings_dialog)
    return;
  HINSTANCE module_handle = GetModuleHandle(chrome::kBrowserResourcesDll);
  settings_dialog = CreateDialog(module_handle,
                                 MAKEINTRESOURCE(IDD_IPC_SETTINGS),
                                 NULL,
                                 &DialogProc);
  ::ShowWindow(settings_dialog, SW_SHOW);
}

}  // namespace

// AboutIPCDialog --------------------------------------------------------------

AboutIPCDialog::AboutIPCDialog()
    : track_toggle_(NULL),
      clear_button_(NULL),
      filter_button_(NULL),
      table_(NULL),
      tracking_(false) {
  SetupControls();
  IPC::Logging::GetInstance()->SetConsumer(this);
}

AboutIPCDialog::~AboutIPCDialog() {
  g_active_dialog = NULL;
  IPC::Logging::GetInstance()->SetConsumer(NULL);
}

// static
void AboutIPCDialog::RunDialog() {
  if (!g_active_dialog) {
    g_active_dialog = new AboutIPCDialog;
    views::Widget::CreateWindow(g_active_dialog)->Show();
  } else {
    // TODO(brettw) it would be nice to focus the existing window.
  }
}

void AboutIPCDialog::SetupControls() {
  views::GridLayout* layout = views::GridLayout::CreatePanel(this);
  SetLayoutManager(layout);

  track_toggle_ = new views::TextButton(this, kStartTrackingLabel);
  clear_button_ = new views::TextButton(this, kClearLabel);
  filter_button_ = new views::TextButton(this, kFilterLabel);

  table_ = new views::NativeViewHost;

  static const int first_column_set = 1;
  views::ColumnSet* column_set = layout->AddColumnSet(first_column_set);
  column_set->AddColumn(views::GridLayout::CENTER, views::GridLayout::CENTER,
                        33.33f, views::GridLayout::FIXED, 0, 0);
  column_set->AddColumn(views::GridLayout::CENTER, views::GridLayout::CENTER,
                        33.33f, views::GridLayout::FIXED, 0, 0);
  column_set->AddColumn(views::GridLayout::CENTER, views::GridLayout::CENTER,
                        33.33f, views::GridLayout::FIXED, 0, 0);

  static const int table_column_set = 2;
  column_set = layout->AddColumnSet(table_column_set);
  column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL,
                        100.0f, views::GridLayout::FIXED, 0, 0);

  layout->StartRow(0, first_column_set);
  layout->AddView(track_toggle_);
  layout->AddView(clear_button_);
  layout->AddView(filter_button_);
  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
  layout->StartRow(1.0f, table_column_set);
  layout->AddView(table_);
}

gfx::Size AboutIPCDialog::GetPreferredSize() {
  return gfx::Size(800, 400);
}

views::View* AboutIPCDialog::GetContentsView() {
  return this;
}

int AboutIPCDialog::GetDialogButtons() const {
  // Don't want OK or Cancel.
  return 0;
}

string16 AboutIPCDialog::GetWindowTitle() const {
  return ASCIIToUTF16("about:ipc");
}

void AboutIPCDialog::Layout() {
  if (!message_list_.m_hWnd) {
    HWND parent_window = GetWidget()->GetNativeView();

    RECT rect = {0, 0, 10, 10};
    HWND list_hwnd = message_list_.Create(parent_window,
        rect, NULL, WS_CHILD | WS_VISIBLE | LVS_SORTASCENDING);
    message_list_.SetViewType(LVS_REPORT);
    message_list_.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT);

    int column_index = 0;
    message_list_.InsertColumn(kTimeColumn, L"time", LVCFMT_LEFT, 80);
    message_list_.InsertColumn(kChannelColumn, L"channel", LVCFMT_LEFT, 110);
    message_list_.InsertColumn(kMessageColumn, L"message", LVCFMT_LEFT, 240);
    message_list_.InsertColumn(kFlagsColumn, L"flags", LVCFMT_LEFT, 50);
    message_list_.InsertColumn(kDispatchColumn, L"dispatch (ms)", LVCFMT_RIGHT,
                               80);
    message_list_.InsertColumn(kProcessColumn, L"process (ms)", LVCFMT_RIGHT,
                               80);
    message_list_.InsertColumn(kParamsColumn, L"parameters", LVCFMT_LEFT, 500);

    table_->Attach(list_hwnd);
  }

  View::Layout();
}

void AboutIPCDialog::Log(const IPC::LogData& data) {
  if (disabled_messages.find(data.type) != disabled_messages.end())
    return;  // Message type is filtered out.

  base::Time sent = base::Time::FromInternalValue(data.sent);
  base::Time::Exploded exploded;
  sent.LocalExplode(&exploded);
  if (exploded.hour > 12)
    exploded.hour -= 12;

  std::wstring sent_str = StringPrintf(L"%02d:%02d:%02d.%03d",
      exploded.hour, exploded.minute, exploded.second, exploded.millisecond);

  int count = message_list_.GetItemCount();
  int index = message_list_.InsertItem(count, sent_str.c_str());

  message_list_.SetItemText(index, kTimeColumn, sent_str.c_str());
  message_list_.SetItemText(index, kChannelColumn,
                            ASCIIToWide(data.channel).c_str());

  std::string message_name;
  IPC::Logging::GetMessageText(data.type, &message_name, NULL, NULL);
  message_list_.SetItemText(index, kMessageColumn,
                            UTF8ToWide(message_name).c_str());
  message_list_.SetItemText(index, kFlagsColumn,
                            UTF8ToWide(data.flags).c_str());

  int64 time_to_send = (base::Time::FromInternalValue(data.receive) -
      sent).InMilliseconds();
  // time can go backwards by a few ms (see Time), don't show that.
  time_to_send = std::max(static_cast<int>(time_to_send), 0);
  std::wstring temp = StringPrintf(L"%d", time_to_send);
  message_list_.SetItemText(index, kDispatchColumn, temp.c_str());

  int64 time_to_process = (base::Time::FromInternalValue(data.dispatch) -
      base::Time::FromInternalValue(data.receive)).InMilliseconds();
  time_to_process = std::max(static_cast<int>(time_to_process), 0);
  temp = StringPrintf(L"%d", time_to_process);
  message_list_.SetItemText(index, kProcessColumn, temp.c_str());

  message_list_.SetItemText(index, kParamsColumn,
                            UTF8ToWide(data.params).c_str());
  message_list_.EnsureVisible(index, FALSE);
}

bool AboutIPCDialog::CanResize() const {
  return true;
}

void AboutIPCDialog::ButtonPressed(
    views::Button* button, const views::Event& event) {
  if (button == track_toggle_) {
    if (tracking_) {
      track_toggle_->SetText(kStartTrackingLabel);
      tracking_ = false;
      content::EnableIPCLogging(false);
    } else {
      track_toggle_->SetText(kStopTrackingLabel);
      tracking_ = true;
      content::EnableIPCLogging(true);
    }
    track_toggle_->SchedulePaint();
  } else if (button == clear_button_) {
    message_list_.DeleteAllItems();
  } else if (button == filter_button_) {
    RunSettingsDialog(GetWidget()->GetNativeView());
  }
}

namespace browser {

void ShowAboutIPCDialog() {
  AboutIPCDialog::RunDialog();
}

} // namespace browser

#endif  // IPC_MESSAGE_LOG_ENABLED
<commit_msg>views: Return the appropriate value for GetDialogButtons() in AboutIPCDialog.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Need to include this before any other file because it defines
// IPC_MESSAGE_LOG_ENABLED. We need to use it to define
// IPC_MESSAGE_MACROS_LOG_ENABLED so that all_messages.h will generate the
// ViewMsgLog et al. functions.
#include "ipc/ipc_message.h"

#ifdef IPC_MESSAGE_LOG_ENABLED
#define IPC_MESSAGE_MACROS_LOG_ENABLED

// We need to do this real early to be sure IPC_MESSAGE_MACROS_LOG_ENABLED
// doesn't get undefined.
#include "chrome/common/all_messages.h"

#include "chrome/browser/ui/views/about_ipc_dialog.h"

#include <set>

#include "base/string_util.h"
#include "base/threading/thread.h"
#include "base/time.h"
#include "base/utf_string_conversions.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/ui/browser_dialogs.h"
#include "chrome/common/chrome_constants.h"
#include "content/public/browser/content_ipc_logging.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_job.h"
#include "ui/views/controls/button/text_button.h"
#include "ui/views/controls/native/native_view_host.h"
#include "ui/views/layout/grid_layout.h"
#include "ui/views/layout/layout_constants.h"
#include "ui/views/widget/widget.h"

namespace {

// We don't localize this UI since this is a developer-only feature.
const wchar_t kStartTrackingLabel[] = L"Start tracking";
const wchar_t kStopTrackingLabel[] = L"Stop tracking";
const wchar_t kClearLabel[] = L"Clear";
const wchar_t kFilterLabel[] = L"Filter...";

enum {
  kTimeColumn = 0,
  kChannelColumn,
  kMessageColumn,
  kFlagsColumn,
  kDispatchColumn,
  kProcessColumn,
  kParamsColumn,
};

// This class registers the browser IPC logger functions with IPC::Logging.
class RegisterLoggerFuncs {
 public:
  RegisterLoggerFuncs() {
    IPC::Logging::set_log_function_map(&g_log_function_mapping);
  }
};

RegisterLoggerFuncs g_register_logger_funcs;

// The singleton dialog box. This is non-NULL when a dialog is active so we
// know not to create a new one.
AboutIPCDialog* g_active_dialog = NULL;

std::set<int> disabled_messages;

// Settings dialog -------------------------------------------------------------

bool init_done = false;
HWND settings_dialog = NULL;
// Settings.
CListViewCtrl* messages = NULL;

void OnCheck(int id, bool checked) {
  if (!init_done)
    return;

  if (checked)
    disabled_messages.erase(id);
  else
    disabled_messages.insert(id);
}

void InitDialog(HWND hwnd) {
  messages = new CListViewCtrl(::GetDlgItem(hwnd, IDC_Messages));

  messages->SetViewType(LVS_REPORT);
  messages->SetExtendedListViewStyle(LVS_EX_CHECKBOXES);
  messages->ModifyStyle(0, LVS_SORTASCENDING | LVS_NOCOLUMNHEADER);
  messages->InsertColumn(0, L"id", LVCFMT_LEFT, 230);

  LogFunctionMap* log_functions = IPC::Logging::log_function_map();
  for (LogFunctionMap::iterator i = log_functions->begin();
       i != log_functions->end(); ++i) {
    std::string name;
    (*i->second)(&name, NULL, NULL);
    if (name.empty())
      continue;  // Will happen if the message file isn't included above.
    std::wstring wname = UTF8ToWide(name);

    int index = messages->InsertItem(
        LVIF_TEXT | LVIF_PARAM, 0, wname.c_str(), 0, 0, 0, i->first);

    messages->SetItemText(index, 0, wname.c_str());

    if (disabled_messages.find(i->first) == disabled_messages.end())
      messages->SetCheckState(index, TRUE);
  }

  init_done = true;
}

void CloseDialog() {
  delete messages;
  messages = NULL;

  init_done = false;

  ::DestroyWindow(settings_dialog);
  settings_dialog = NULL;

  /* The old version of this code stored the last settings in the preferences.
     But with this dialog, there currently isn't an easy way to get the profile
     to save in the preferences.
  Profile* current_profile = profile();
  if (!current_profile)
    return;
  PrefService* prefs = current_profile->GetPrefs();
  if (!prefs->FindPreference(prefs::kIpcDisabledMessages))
    return;
  ListValue* list = prefs->GetMutableList(prefs::kIpcDisabledMessages);
  list->Clear();
  for (std::set<int>::const_iterator itr = disabled_messages_.begin();
       itr != disabled_messages_.end();
       ++itr) {
    list->Append(Value::CreateIntegerValue(*itr));
  }
  */
}

void OnButtonClick(int id) {
  int count = messages->GetItemCount();
  for (int i = 0; i < count; ++i)
    messages->SetCheckState(i, id == IDC_MessagesAll);
}

INT_PTR CALLBACK DialogProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
  switch (msg) {
    case WM_INITDIALOG:
      InitDialog(hwnd);
      return FALSE;  // Don't set keyboard focus.
    case WM_SYSCOMMAND:
      if (wparam == SC_CLOSE) {
        CloseDialog();
        return FALSE;
      }
      break;
    case WM_NOTIFY: {
      NMLISTVIEW* info = reinterpret_cast<NM_LISTVIEW*>(lparam);
      if (wparam == IDC_Messages && info->hdr.code == LVN_ITEMCHANGED) {
        if (info->uChanged & LVIF_STATE) {
          bool checked = (info->uNewState >> 12) == 2;
          OnCheck(static_cast<int>(info->lParam), checked);
        }
        return FALSE;
      }
      break;
    }
    case WM_COMMAND:
      if (HIWORD(wparam) == BN_CLICKED)
        OnButtonClick(LOWORD(wparam));
      break;
  }
  return FALSE;
}

void RunSettingsDialog(HWND parent) {
  if (settings_dialog)
    return;
  HINSTANCE module_handle = GetModuleHandle(chrome::kBrowserResourcesDll);
  settings_dialog = CreateDialog(module_handle,
                                 MAKEINTRESOURCE(IDD_IPC_SETTINGS),
                                 NULL,
                                 &DialogProc);
  ::ShowWindow(settings_dialog, SW_SHOW);
}

}  // namespace

// AboutIPCDialog --------------------------------------------------------------

AboutIPCDialog::AboutIPCDialog()
    : track_toggle_(NULL),
      clear_button_(NULL),
      filter_button_(NULL),
      table_(NULL),
      tracking_(false) {
  SetupControls();
  IPC::Logging::GetInstance()->SetConsumer(this);
}

AboutIPCDialog::~AboutIPCDialog() {
  g_active_dialog = NULL;
  IPC::Logging::GetInstance()->SetConsumer(NULL);
}

// static
void AboutIPCDialog::RunDialog() {
  if (!g_active_dialog) {
    g_active_dialog = new AboutIPCDialog;
    views::Widget::CreateWindow(g_active_dialog)->Show();
  } else {
    // TODO(brettw) it would be nice to focus the existing window.
  }
}

void AboutIPCDialog::SetupControls() {
  views::GridLayout* layout = views::GridLayout::CreatePanel(this);
  SetLayoutManager(layout);

  track_toggle_ = new views::TextButton(this, kStartTrackingLabel);
  clear_button_ = new views::TextButton(this, kClearLabel);
  filter_button_ = new views::TextButton(this, kFilterLabel);

  table_ = new views::NativeViewHost;

  static const int first_column_set = 1;
  views::ColumnSet* column_set = layout->AddColumnSet(first_column_set);
  column_set->AddColumn(views::GridLayout::CENTER, views::GridLayout::CENTER,
                        33.33f, views::GridLayout::FIXED, 0, 0);
  column_set->AddColumn(views::GridLayout::CENTER, views::GridLayout::CENTER,
                        33.33f, views::GridLayout::FIXED, 0, 0);
  column_set->AddColumn(views::GridLayout::CENTER, views::GridLayout::CENTER,
                        33.33f, views::GridLayout::FIXED, 0, 0);

  static const int table_column_set = 2;
  column_set = layout->AddColumnSet(table_column_set);
  column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL,
                        100.0f, views::GridLayout::FIXED, 0, 0);

  layout->StartRow(0, first_column_set);
  layout->AddView(track_toggle_);
  layout->AddView(clear_button_);
  layout->AddView(filter_button_);
  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
  layout->StartRow(1.0f, table_column_set);
  layout->AddView(table_);
}

gfx::Size AboutIPCDialog::GetPreferredSize() {
  return gfx::Size(800, 400);
}

views::View* AboutIPCDialog::GetContentsView() {
  return this;
}

int AboutIPCDialog::GetDialogButtons() const {
  return ui::DIALOG_BUTTON_NONE;
}

string16 AboutIPCDialog::GetWindowTitle() const {
  return ASCIIToUTF16("about:ipc");
}

void AboutIPCDialog::Layout() {
  if (!message_list_.m_hWnd) {
    HWND parent_window = GetWidget()->GetNativeView();

    RECT rect = {0, 0, 10, 10};
    HWND list_hwnd = message_list_.Create(parent_window,
        rect, NULL, WS_CHILD | WS_VISIBLE | LVS_SORTASCENDING);
    message_list_.SetViewType(LVS_REPORT);
    message_list_.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT);

    int column_index = 0;
    message_list_.InsertColumn(kTimeColumn, L"time", LVCFMT_LEFT, 80);
    message_list_.InsertColumn(kChannelColumn, L"channel", LVCFMT_LEFT, 110);
    message_list_.InsertColumn(kMessageColumn, L"message", LVCFMT_LEFT, 240);
    message_list_.InsertColumn(kFlagsColumn, L"flags", LVCFMT_LEFT, 50);
    message_list_.InsertColumn(kDispatchColumn, L"dispatch (ms)", LVCFMT_RIGHT,
                               80);
    message_list_.InsertColumn(kProcessColumn, L"process (ms)", LVCFMT_RIGHT,
                               80);
    message_list_.InsertColumn(kParamsColumn, L"parameters", LVCFMT_LEFT, 500);

    table_->Attach(list_hwnd);
  }

  View::Layout();
}

void AboutIPCDialog::Log(const IPC::LogData& data) {
  if (disabled_messages.find(data.type) != disabled_messages.end())
    return;  // Message type is filtered out.

  base::Time sent = base::Time::FromInternalValue(data.sent);
  base::Time::Exploded exploded;
  sent.LocalExplode(&exploded);
  if (exploded.hour > 12)
    exploded.hour -= 12;

  std::wstring sent_str = StringPrintf(L"%02d:%02d:%02d.%03d",
      exploded.hour, exploded.minute, exploded.second, exploded.millisecond);

  int count = message_list_.GetItemCount();
  int index = message_list_.InsertItem(count, sent_str.c_str());

  message_list_.SetItemText(index, kTimeColumn, sent_str.c_str());
  message_list_.SetItemText(index, kChannelColumn,
                            ASCIIToWide(data.channel).c_str());

  std::string message_name;
  IPC::Logging::GetMessageText(data.type, &message_name, NULL, NULL);
  message_list_.SetItemText(index, kMessageColumn,
                            UTF8ToWide(message_name).c_str());
  message_list_.SetItemText(index, kFlagsColumn,
                            UTF8ToWide(data.flags).c_str());

  int64 time_to_send = (base::Time::FromInternalValue(data.receive) -
      sent).InMilliseconds();
  // time can go backwards by a few ms (see Time), don't show that.
  time_to_send = std::max(static_cast<int>(time_to_send), 0);
  std::wstring temp = StringPrintf(L"%d", time_to_send);
  message_list_.SetItemText(index, kDispatchColumn, temp.c_str());

  int64 time_to_process = (base::Time::FromInternalValue(data.dispatch) -
      base::Time::FromInternalValue(data.receive)).InMilliseconds();
  time_to_process = std::max(static_cast<int>(time_to_process), 0);
  temp = StringPrintf(L"%d", time_to_process);
  message_list_.SetItemText(index, kProcessColumn, temp.c_str());

  message_list_.SetItemText(index, kParamsColumn,
                            UTF8ToWide(data.params).c_str());
  message_list_.EnsureVisible(index, FALSE);
}

bool AboutIPCDialog::CanResize() const {
  return true;
}

void AboutIPCDialog::ButtonPressed(
    views::Button* button, const views::Event& event) {
  if (button == track_toggle_) {
    if (tracking_) {
      track_toggle_->SetText(kStartTrackingLabel);
      tracking_ = false;
      content::EnableIPCLogging(false);
    } else {
      track_toggle_->SetText(kStopTrackingLabel);
      tracking_ = true;
      content::EnableIPCLogging(true);
    }
    track_toggle_->SchedulePaint();
  } else if (button == clear_button_) {
    message_list_.DeleteAllItems();
  } else if (button == filter_button_) {
    RunSettingsDialog(GetWidget()->GetNativeView());
  }
}

namespace browser {

void ShowAboutIPCDialog() {
  AboutIPCDialog::RunDialog();
}

} // namespace browser

#endif  // IPC_MESSAGE_LOG_ENABLED
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/installer/util/self_reg_work_item.h"

#include "base/logging.h"
#include "chrome/installer/util/logging_installer.h"

// Default registration export names.
const char kDefaultRegistrationEntryPoint[] = "DllRegisterServer";
const char kDefaultUnregistrationEntryPoint[] = "DllUnregisterServer";

// User-level registration export names.
const char kUserRegistrationEntryPoint[] = "DllRegisterUserServer";
const char kUserUnregistrationEntryPoint[] = "DllUnregisterUserServer";

SelfRegWorkItem::SelfRegWorkItem(const std::wstring& dll_path,
                                 bool do_register,
                                 bool user_level_registration)
    : do_register_(do_register), dll_path_(dll_path),
      user_level_registration_(user_level_registration) {
}

SelfRegWorkItem::~SelfRegWorkItem() {
}

bool SelfRegWorkItem::RegisterDll(bool do_register) {
  HMODULE dll_module = ::LoadLibraryEx(dll_path_.c_str(), NULL,
                                       LOAD_WITH_ALTERED_SEARCH_PATH);
  bool success = false;
  if (NULL != dll_module) {
    PROC register_server_func = NULL;
    if (do_register) {
      register_server_func = ::GetProcAddress(dll_module,
          user_level_registration_ ? kUserRegistrationEntryPoint :
                                     kDefaultRegistrationEntryPoint);
    } else {
      register_server_func = ::GetProcAddress(dll_module,
          user_level_registration_ ? kUserUnregistrationEntryPoint :
                                     kDefaultUnregistrationEntryPoint);
    }

    if (NULL != register_server_func) {
      success = SUCCEEDED(register_server_func());
      if (!success) {
        LOG(ERROR) << "Failed to " << (do_register ? "register" : "unregister")
                   << " DLL at " << dll_path_.c_str();
      }
    }
    ::FreeLibrary(dll_module);
  }
  return success;
}

bool SelfRegWorkItem::Do() {
  return RegisterDll(do_register_);
}

void SelfRegWorkItem::Rollback() {
  RegisterDll(!do_register_);
}
<commit_msg>Add some verbose logging when registering COM components.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/installer/util/self_reg_work_item.h"

#include "base/logging.h"
#include "chrome/installer/util/logging_installer.h"

// Default registration export names.
const char kDefaultRegistrationEntryPoint[] = "DllRegisterServer";
const char kDefaultUnregistrationEntryPoint[] = "DllUnregisterServer";

// User-level registration export names.
const char kUserRegistrationEntryPoint[] = "DllRegisterUserServer";
const char kUserUnregistrationEntryPoint[] = "DllUnregisterUserServer";

SelfRegWorkItem::SelfRegWorkItem(const std::wstring& dll_path,
                                 bool do_register,
                                 bool user_level_registration)
    : do_register_(do_register), dll_path_(dll_path),
      user_level_registration_(user_level_registration) {
}

SelfRegWorkItem::~SelfRegWorkItem() {
}

bool SelfRegWorkItem::RegisterDll(bool do_register) {
  VLOG(1) << "COM " << (do_register ? "registration of " : "unregistration of ")
      << dll_path_;

  HMODULE dll_module = ::LoadLibraryEx(dll_path_.c_str(), NULL,
                                       LOAD_WITH_ALTERED_SEARCH_PATH);
  bool success = false;
  if (NULL != dll_module) {
    PROC register_server_func = NULL;
    if (do_register) {
      register_server_func = ::GetProcAddress(dll_module,
          user_level_registration_ ? kUserRegistrationEntryPoint :
                                     kDefaultRegistrationEntryPoint);
    } else {
      register_server_func = ::GetProcAddress(dll_module,
          user_level_registration_ ? kUserUnregistrationEntryPoint :
                                     kDefaultUnregistrationEntryPoint);
    }

    if (NULL != register_server_func) {
      success = SUCCEEDED(register_server_func());
      if (!success) {
        LOG(ERROR) << "Failed to " << (do_register ? "register" : "unregister")
                   << " DLL at " << dll_path_.c_str();
      }
    }
    ::FreeLibrary(dll_module);
  } else {
    LOG(WARNING) << "Failed to load: " << dll_path_;
  }
  return success;
}

bool SelfRegWorkItem::Do() {
  return RegisterDll(do_register_);
}

void SelfRegWorkItem::Rollback() {
  RegisterDll(!do_register_);
}
<|endoftext|>


<commit_before><commit_msg>Better message to the log when migrating across versions.<commit_after><|endoftext|>


<commit_before>/*
 * DesktopUpdateChecker.cpp
 *
 * Copyright (C) 2009-11 by RStudio, Inc.
 *
 * This program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "DesktopUpdateChecker.hpp"

#include <QDesktopServices>
#include <QMessageBox>
#include <QPushButton>

#include <core/Log.hpp>
#include <core/Error.hpp>

#include <core/http/Util.hpp>

#include "DesktopOptions.hpp"
#include "DesktopURLDownloader.hpp"
#include "DesktopUpdateAvailableDialog.hpp"

#include "DesktopUtils.hpp"

#include "config.h"

using namespace core;

namespace desktop {

QUrl UpdateChecker::checkForUpdatesURL()
{
   QUrl url(QString::fromAscii("http://www.rstudio.org/links/check_for_update"));
   url.addQueryItem(QString::fromAscii("version"), QString::fromAscii(RSTUDIO_VERSION));
   QString platform;
#if defined(_WIN32)
   platform = QString::fromAscii("windows");
#elif defined(__APPLE__)
   platform = QString::fromAscii("mac");
#else
   platform = QString::fromAscii("linux");
#endif
   url.addQueryItem(QString::fromAscii("os"), platform);
   return url;
}

void UpdateChecker::performCheck(bool manuallyInvoked)
{
   // build URL (specify key-value pair return)
   QUrl url = checkForUpdatesURL();
   url.addQueryItem(QString::fromAscii("format"), QString::fromAscii("kvp"));

   // download manifest (URL downlader frees itself)
   URLDownloader* pURLDownloader = new URLDownloader(url,
                                                     10000,
                                                     manuallyInvoked,
                                                     pOwnerWindow_);
   connect(pURLDownloader, SIGNAL(downloadError(const QString&)),
           this, SLOT(manifestDownloadError(const QString&)));
   connect(pURLDownloader, SIGNAL(downloadComplete(const QByteArray&)),
           this, SLOT(manifestDownloadComplete(const QByteArray&)));
}

void UpdateChecker::manifestDownloadError(const QString &message)
{
   LOG_ERROR_MESSAGE("Error downloading manifest: " + std::string(message.toUtf8().constData()));

   URLDownloader* pURLDownloader = qobject_cast<URLDownloader*>(sender());
   if (pURLDownloader && pURLDownloader->manuallyInvoked())
   {
      // WA_DeleteOnClose
      QMessageBox* pMsg = new QMessageBox(
            safeMessageBoxIcon(QMessageBox::Warning),
            QString::fromUtf8("Error Checking for Updates"),
            QString::fromUtf8("An error occurred while checking for updates:\n\n")
            + message,
            QMessageBox::NoButton,
            pOwnerWindow_,
            Qt::Sheet | Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint);
      pMsg->setWindowModality(Qt::WindowModal);
      pMsg->setAttribute(Qt::WA_DeleteOnClose);
      pMsg->addButton(new QPushButton(QString::fromUtf8("OK")), QMessageBox::AcceptRole);
      pMsg->show();
   }
}

void UpdateChecker::manifestDownloadComplete(const QByteArray& data)
{
   // parse manifest
   std::string manifest(data.constData(), data.size());
   http::Fields fields;
   http::util::parseForm(manifest, &fields);

   // get the list of ignored updates
   QStringList ignoredVersions = options().ignoredUpdateVersions();

   URLDownloader* pURLDownloader = qobject_cast<URLDownloader*>(sender());

   // is there an update which we haven't already chosen to ignore?
   std::string stdUpdateVersion = http::util::fieldValue(fields, "update-version");
   QString updateVersion = QString::fromUtf8(stdUpdateVersion.c_str());
   if ( (updateVersion.size() > 0) &&
        (!ignoredVersions.contains(updateVersion) || pURLDownloader->manuallyInvoked()) )
   {
      // get update info
      std::string updateURL = http::util::fieldValue(fields, "update-url");
      std::string updateMessage = http::util::fieldValue(fields, "update-message");
      int isUrgent = http::util::fieldValue<int>(fields, "update-urgent", 0);
      DesktopUpdateInfo updateInfo;
      updateInfo.currentVersion = QString::fromUtf8(RSTUDIO_VERSION);
      updateInfo.updatedVersion = updateVersion;
      updateInfo.updateURL = QString::fromUtf8(updateURL.c_str());
      updateInfo.updateMessage = QString::fromUtf8(updateMessage.c_str());
      updateInfo.isUrgent = isUrgent != 0;

      // invoke dialog
      DesktopUpdateAvailableDialog dialog(updateInfo, pOwnerWindow_);
      int result = dialog.exec();

      // record if we are permanently ignoring
      switch (result)
      {
      case DesktopUpdateAvailableDialog::Accepted:
         QDesktopServices::openUrl(QUrl(updateInfo.updateURL));
         break;
      case DesktopUpdateAvailableDialog::Rejected:
         break;
      case DesktopUpdateAvailableDialog::Ignored:
         ignoredVersions.append(updateVersion);
         options().setIgnoredUpdateVersions(ignoredVersions);
         break;
      }
   }
   else
   {
      if (pURLDownloader && pURLDownloader->manuallyInvoked())
      {
         // WA_DeleteOnClose
         QMessageBox* pMsg = new QMessageBox(
               safeMessageBoxIcon(QMessageBox::Information),
               QString::fromUtf8("No Update Available"),
               QString::fromUtf8("You're using the newest version of RStudio."),
               QMessageBox::NoButton,
               pOwnerWindow_,
               Qt::Sheet | Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint);
         pMsg->setWindowModality(Qt::WindowModal);
         pMsg->setAttribute(Qt::WA_DeleteOnClose);
         pMsg->addButton(new QPushButton(QString::fromUtf8("OK")), QMessageBox::AcceptRole);
         pMsg->show();
      }
   }
}

} // namespace desktop
<commit_msg>Check for updates passes a query param indicating whether this is a manual check<commit_after>/*
 * DesktopUpdateChecker.cpp
 *
 * Copyright (C) 2009-11 by RStudio, Inc.
 *
 * This program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "DesktopUpdateChecker.hpp"

#include <QDesktopServices>
#include <QMessageBox>
#include <QPushButton>

#include <core/Log.hpp>
#include <core/Error.hpp>

#include <core/http/Util.hpp>

#include "DesktopOptions.hpp"
#include "DesktopURLDownloader.hpp"
#include "DesktopUpdateAvailableDialog.hpp"

#include "DesktopUtils.hpp"

#include "config.h"

using namespace core;

namespace desktop {

QUrl UpdateChecker::checkForUpdatesURL()
{
   QUrl url(QString::fromAscii("http://www.rstudio.org/links/check_for_update"));
   url.addQueryItem(QString::fromAscii("version"), QString::fromAscii(RSTUDIO_VERSION));
   QString platform;
#if defined(_WIN32)
   platform = QString::fromAscii("windows");
#elif defined(__APPLE__)
   platform = QString::fromAscii("mac");
#else
   platform = QString::fromAscii("linux");
#endif
   url.addQueryItem(QString::fromAscii("os"), platform);
   return url;
}

void UpdateChecker::performCheck(bool manuallyInvoked)
{
   // build URL (specify key-value pair return)
   QUrl url = checkForUpdatesURL();
   url.addQueryItem(QString::fromAscii("format"), QString::fromAscii("kvp"));
   if (manuallyInvoked)
      url.addQueryItem(QString::fromAscii("manual"), QString::fromAscii("true"));

   // download manifest (URL downlader frees itself)
   URLDownloader* pURLDownloader = new URLDownloader(url,
                                                     10000,
                                                     manuallyInvoked,
                                                     pOwnerWindow_);
   connect(pURLDownloader, SIGNAL(downloadError(const QString&)),
           this, SLOT(manifestDownloadError(const QString&)));
   connect(pURLDownloader, SIGNAL(downloadComplete(const QByteArray&)),
           this, SLOT(manifestDownloadComplete(const QByteArray&)));
}

void UpdateChecker::manifestDownloadError(const QString &message)
{
   LOG_ERROR_MESSAGE("Error downloading manifest: " + std::string(message.toUtf8().constData()));

   URLDownloader* pURLDownloader = qobject_cast<URLDownloader*>(sender());
   if (pURLDownloader && pURLDownloader->manuallyInvoked())
   {
      // WA_DeleteOnClose
      QMessageBox* pMsg = new QMessageBox(
            safeMessageBoxIcon(QMessageBox::Warning),
            QString::fromUtf8("Error Checking for Updates"),
            QString::fromUtf8("An error occurred while checking for updates:\n\n")
            + message,
            QMessageBox::NoButton,
            pOwnerWindow_,
            Qt::Sheet | Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint);
      pMsg->setWindowModality(Qt::WindowModal);
      pMsg->setAttribute(Qt::WA_DeleteOnClose);
      pMsg->addButton(new QPushButton(QString::fromUtf8("OK")), QMessageBox::AcceptRole);
      pMsg->show();
   }
}

void UpdateChecker::manifestDownloadComplete(const QByteArray& data)
{
   // parse manifest
   std::string manifest(data.constData(), data.size());
   http::Fields fields;
   http::util::parseForm(manifest, &fields);

   // get the list of ignored updates
   QStringList ignoredVersions = options().ignoredUpdateVersions();

   URLDownloader* pURLDownloader = qobject_cast<URLDownloader*>(sender());

   // is there an update which we haven't already chosen to ignore?
   std::string stdUpdateVersion = http::util::fieldValue(fields, "update-version");
   QString updateVersion = QString::fromUtf8(stdUpdateVersion.c_str());
   if ( (updateVersion.size() > 0) &&
        (!ignoredVersions.contains(updateVersion) || pURLDownloader->manuallyInvoked()) )
   {
      // get update info
      std::string updateURL = http::util::fieldValue(fields, "update-url");
      std::string updateMessage = http::util::fieldValue(fields, "update-message");
      int isUrgent = http::util::fieldValue<int>(fields, "update-urgent", 0);
      DesktopUpdateInfo updateInfo;
      updateInfo.currentVersion = QString::fromUtf8(RSTUDIO_VERSION);
      updateInfo.updatedVersion = updateVersion;
      updateInfo.updateURL = QString::fromUtf8(updateURL.c_str());
      updateInfo.updateMessage = QString::fromUtf8(updateMessage.c_str());
      updateInfo.isUrgent = isUrgent != 0;

      // invoke dialog
      DesktopUpdateAvailableDialog dialog(updateInfo, pOwnerWindow_);
      int result = dialog.exec();

      // record if we are permanently ignoring
      switch (result)
      {
      case DesktopUpdateAvailableDialog::Accepted:
         QDesktopServices::openUrl(QUrl(updateInfo.updateURL));
         break;
      case DesktopUpdateAvailableDialog::Rejected:
         break;
      case DesktopUpdateAvailableDialog::Ignored:
         ignoredVersions.append(updateVersion);
         options().setIgnoredUpdateVersions(ignoredVersions);
         break;
      }
   }
   else
   {
      if (pURLDownloader && pURLDownloader->manuallyInvoked())
      {
         // WA_DeleteOnClose
         QMessageBox* pMsg = new QMessageBox(
               safeMessageBoxIcon(QMessageBox::Information),
               QString::fromUtf8("No Update Available"),
               QString::fromUtf8("You're using the newest version of RStudio."),
               QMessageBox::NoButton,
               pOwnerWindow_,
               Qt::Sheet | Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint);
         pMsg->setWindowModality(Qt::WindowModal);
         pMsg->setAttribute(Qt::WA_DeleteOnClose);
         pMsg->addButton(new QPushButton(QString::fromUtf8("OK")), QMessageBox::AcceptRole);
         pMsg->show();
      }
   }
}

} // namespace desktop
<|endoftext|>


<commit_before>/*
 * Funambol is a mobile platform developed by Funambol, Inc.
 * Copyright (C) 2003 - 2007 Funambol, Inc.
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License version 3 as published by
 * the Free Software Foundation with the addition of the following permission
 * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
 * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE
 * WARRANTY OF NON INFRINGEMENT  OF THIRD PARTY RIGHTS.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, see http://www.gnu.org/licenses or write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301 USA.
 *
 * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite
 * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
 *
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License version 3.
 *
 * In accordance with Section 7(b) of the GNU Affero General Public License
 * version 3, these Appropriate Legal Notices must retain the display of the
 * "Powered by Funambol" logo. If the display of the logo is not reasonably
 * feasible for technical reasons, the Appropriate Legal Notices must display
 * the words "Powered by Funambol".
 */

#include "base/fscapi.h"

#if FUN_TRANSPORT_AGENT == FUN_MAC_TRANSPORT_AGENT

#include <Foundation/Foundation.h>
#include <CoreFoundation/CoreFoundation.h>
#if defined(FUN_IPHONE)
#include <SystemConfiguration/SystemConfiguration.h>
#include <SystemConfiguration/SCNetworkReachability.h>
#if TARGET_IPHONE_SIMULATOR
#include <CoreServices/CoreServices.h>
#else
#include <CFNetwork/CFNetwork.h>
#endif
#else
#include <CoreServices/CoreServices.h>
#endif

#include "http/MacTransportAgent.h"
#include "http/constants.h"

#include "base/util/utils.h"
#include "base/util/StringBuffer.h"

USE_NAMESPACE

MacTransportAgent::MacTransportAgent() : TransportAgent() {}

MacTransportAgent::~MacTransportAgent() {}

/*
 * Constructor.
 * In this implementation newProxy is ignored, since proxy configuration
 * is taken from the WinInet subsystem.
 *
 * @param url the url where messages will be sent with sendMessage()
 * @param proxy proxy information or NULL if no proxy should be used
 */
MacTransportAgent::MacTransportAgent(URL& newURL, Proxy& newProxy, unsigned int maxResponseTimeout)
: TransportAgent(newURL, newProxy, maxResponseTimeout)
{}

/*
 * Sends the given SyncML message to the server specified
 * by the instal property 'url'. Returns the response status code or -1
 * if it was not possible initialize the connection.
 *
 * Use getResponse() to get the server response.
 */
char* MacTransportAgent::sendMessage(const char* msg){
    LOG.debug("MacTransportAgent::sendMessage begin");
    if(!msg) {
        LOG.error("MacTransportAgent::sendMessage error: NULL message.");
        setError(ERR_NETWORK_INIT, "MacTransportAgent::sendMessage error: NULL message.");
        return NULL;
    }

    bool gotflags = true;
    bool isReachable = true;
    bool noConnectionRequired = true;

    StringBuffer result;
    CFIndex bytesRead = 1;
    int statusCode = -1;

#if defined(FUN_IPHONE)
    SCNetworkReachabilityFlags        flags;
    SCNetworkReachabilityRef scnReachRef = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, url.host);

    gotflags = SCNetworkReachabilityGetFlags(scnReachRef, &flags);
    isReachable = flags & kSCNetworkReachabilityFlagsReachable;
    noConnectionRequired = !(flags & kSCNetworkReachabilityFlagsConnectionRequired);
    if ((flags & kSCNetworkReachabilityFlagsIsWWAN)) {
        noConnectionRequired = true;
    }
    CFRelease(scnReachRef);
#endif

    if ( gotflags && isReachable && noConnectionRequired ){
        char* ret=0;
        // size_t size = strlen(msg);
        LOG.debug("Requesting resource %s at %s:%d", url.resource, url.host, url.port);

        LOG.debug("Sending HTTP Request: %s", msg);

        // Construct some headers
        CFStringRef headerFieldName = CFSTR("Content-Type");
        CFStringRef headerFieldValue = CFSTR("application/vnd.syncml+xml");

        // Construct URL
        CFStringRef CFurl =  CFStringCreateWithCString(NULL, url.fullURL, kCFStringEncodingUTF8);
        CFURLRef myURL = CFURLCreateWithString(kCFAllocatorDefault, CFurl, NULL);

        CFStringRef requestMethod = CFSTR("POST");

        CFHTTPMessageRef httpRequest =
        CFHTTPMessageCreateRequest(kCFAllocatorDefault, requestMethod, myURL, kCFHTTPVersion1_1);
        CFStringRef useragent = CFStringCreateWithCString(NULL, getUserAgent(), kCFStringEncodingUTF8);
        CFHTTPMessageSetHeaderFieldValue(httpRequest, CFSTR("user-agent"),  useragent);
        if(!httpRequest){
            LOG.error("MacTransportAgent::sendMessage error: CFHTTPMessageCreateRequest Error.");
            setError(ERR_NETWORK_INIT, "MacTransportAgent::sendMessage error: CFHTTPMessageCreateRequest Error.");

            goto finally;
        }

        CFDataRef bodyData = CFDataCreate(kCFAllocatorDefault, (const UInt8*)msg, strlen(msg));
        if (!bodyData){
            LOG.error("MacTransportAgent::sendMessage error: CFHTTPMessageCreateRequest Error.");
            setError(ERR_NETWORK_INIT, "MacTransportAgent::sendMessage error: CFHTTPMessageCreateRequest Error.");
            goto finally;
        }
        CFHTTPMessageSetBody(httpRequest, bodyData);
        CFHTTPMessageSetHeaderFieldValue(httpRequest, headerFieldName, headerFieldValue);

        CFReadStreamRef responseStream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, httpRequest);

        bool setProperty;
        //if we are trying to sync on a https server we have to have a trusted certificate.
        //no self signed certificates are accepted
        if(strcmp(url.protocol, "https")==0){
            NSDictionary *sslProperties;
            sslProperties = [NSDictionary dictionaryWithObjectsAndKeys:
                                               (NSString *)kCFStreamSocketSecurityLevelNegotiatedSSL, kCFStreamSSLLevel,
                                               kCFBooleanFalse, kCFStreamSSLAllowsAnyRoot,
                                               kCFBooleanTrue, kCFStreamSSLValidatesCertificateChain,
                                               kCFNull, kCFStreamSSLPeerName,
                                               nil];

            setProperty = CFReadStreamSetProperty( responseStream,
                                                  kCFStreamPropertySSLSettings,
                                                  sslProperties );
            [sslProperties release];
        }

        if (!CFReadStreamOpen(responseStream)) {//Sends request
            LOG.error("Failed to send HTTP request...");
        }

#define READ_SIZE 1000

        UInt8   buffer[READ_SIZE];
        while ( (bytesRead = CFReadStreamRead(responseStream, buffer, READ_SIZE-1)) > 0)
        {
            //   Convert what was read to a C-string
            buffer[bytesRead] = 0;
            //   Append it to the reply string
            result.append((const char*)buffer);
        }

        CFHTTPMessageRef reply = (CFHTTPMessageRef) CFReadStreamCopyProperty( responseStream, kCFStreamPropertyHTTPResponseHeader);

        // Pull the status code from the headers
        if (reply) {
            statusCode = CFHTTPMessageGetResponseStatusCode(reply);
            CFRelease(reply);
        }

        LOG.debug("Status Code: %d", statusCode);
        LOG.debug("Result: %s", result.c_str());

        switch (statusCode) {
            case 0: {
                LOG.debug("Http request successful.");

                // No errors, copy the response
                // TODO: avoid byte copy
                ret = stringdup(result.c_str());

                break;
            }
            case 200: {
                LOG.debug("Http request successful.");

                // No errors, copy the response
                // TODO: avoid byte copy
                ret = stringdup(result.c_str());

                break;
            }
            case -1: {                    // no connection (TODO: implement retry)
                setErrorF(ERR_SERVER_ERROR, "Network error in server receiving data. ");
                LOG.error("%s", getLastErrorMsg());

                break;
            }
            case 400: {                    // 400 bad request error. TODO: retry to send the message
                setErrorF(ERR_SERVER_ERROR, "HTTP server error: %d. Server failure.", statusCode);
                LOG.debug("%s", getLastErrorMsg());

                break;
            }
            case 500: {     // 500 -> out code 2052
                setErrorF(ERR_SERVER_ERROR, "HTTP server error: %d. Server failure.", statusCode);
                LOG.debug("%s", getLastErrorMsg());
                break;
            }
            case 404: {         // 404 -> out code 2060
                setErrorF(ERR_HTTP_NOT_FOUND, "HTTP request error: resource not found (status %d)", statusCode);
                LOG.debug("%s", getLastErrorMsg());
                break;
            }
            case 408: {   // 408 -> out code 2061
                setErrorF(ERR_HTTP_REQUEST_TIMEOUT, "HTTP request error: server timed out waiting for request (status %d)", statusCode);
                LOG.debug("%s", getLastErrorMsg());
                break;
            }

            default: {
                setErrorF(statusCode, "HTTP request error: status received = %d", statusCode);
                LOG.error("%s", getLastErrorMsg());
            }
        }

    finally:
        CFRelease(headerFieldName);
        CFRelease(headerFieldValue);
        CFRelease(CFurl);
        CFRelease(myURL);
        CFRelease(httpRequest);
        CFRelease(bodyData);
        CFRelease(responseStream);
        CFRelease(requestMethod);
        CFRelease(useragent);

        LOG.debug("MacTransportAgent::sendMessage end");
        return ret;
    }else{
        setErrorF(ERR_CONNECT, "Network error: the attempt to connect to the server failed -> exit");
        LOG.debug("%s", getLastErrorMsg());
        LOG.debug("MacTransportAgent::sendMessage end");
        return NULL;
    }
}

#endif

<commit_msg>corrected ssl support<commit_after>/*
 * Funambol is a mobile platform developed by Funambol, Inc.
 * Copyright (C) 2003 - 2007 Funambol, Inc.
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License version 3 as published by
 * the Free Software Foundation with the addition of the following permission
 * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
 * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE
 * WARRANTY OF NON INFRINGEMENT  OF THIRD PARTY RIGHTS.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, see http://www.gnu.org/licenses or write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301 USA.
 *
 * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite
 * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
 *
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License version 3.
 *
 * In accordance with Section 7(b) of the GNU Affero General Public License
 * version 3, these Appropriate Legal Notices must retain the display of the
 * "Powered by Funambol" logo. If the display of the logo is not reasonably
 * feasible for technical reasons, the Appropriate Legal Notices must display
 * the words "Powered by Funambol".
 */

#include "base/fscapi.h"

#if FUN_TRANSPORT_AGENT == FUN_MAC_TRANSPORT_AGENT

#include <Foundation/Foundation.h>
#include <CoreFoundation/CoreFoundation.h>
#if defined(FUN_IPHONE)
#include <SystemConfiguration/SystemConfiguration.h>
#include <SystemConfiguration/SCNetworkReachability.h>
#if TARGET_IPHONE_SIMULATOR
#include <CoreServices/CoreServices.h>
#else
#include <CFNetwork/CFNetwork.h>
#endif
#else
#include <CoreServices/CoreServices.h>
#endif

#include "http/MacTransportAgent.h"
#include "http/constants.h"

#include "base/util/utils.h"
#include "base/util/StringBuffer.h"

USE_NAMESPACE

MacTransportAgent::MacTransportAgent() : TransportAgent() {}

MacTransportAgent::~MacTransportAgent() {}

/*
 * Constructor.
 * In this implementation newProxy is ignored, since proxy configuration
 * is taken from the WinInet subsystem.
 *
 * @param url the url where messages will be sent with sendMessage()
 * @param proxy proxy information or NULL if no proxy should be used
 */
MacTransportAgent::MacTransportAgent(URL& newURL, Proxy& newProxy, unsigned int maxResponseTimeout)
: TransportAgent(newURL, newProxy, maxResponseTimeout)
{}

/*
 * Sends the given SyncML message to the server specified
 * by the instal property 'url'. Returns the response status code or -1
 * if it was not possible initialize the connection.
 *
 * Use getResponse() to get the server response.
 */
char* MacTransportAgent::sendMessage(const char* msg){
    LOG.debug("MacTransportAgent::sendMessage begin");
    if(!msg) {
        LOG.error("MacTransportAgent::sendMessage error: NULL message.");
        setError(ERR_NETWORK_INIT, "MacTransportAgent::sendMessage error: NULL message.");
        return NULL;
    }

    bool gotflags = true;
    bool isReachable = true;
    bool noConnectionRequired = true;

    StringBuffer result;
    CFIndex bytesRead = 1;
    int statusCode = -1;

#if defined(FUN_IPHONE)
    SCNetworkReachabilityFlags        flags;
    SCNetworkReachabilityRef scnReachRef = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, url.host);

    gotflags = SCNetworkReachabilityGetFlags(scnReachRef, &flags);
    isReachable = flags & kSCNetworkReachabilityFlagsReachable;
    noConnectionRequired = !(flags & kSCNetworkReachabilityFlagsConnectionRequired);
    if ((flags & kSCNetworkReachabilityFlagsIsWWAN)) {
        noConnectionRequired = true;
    }
    CFRelease(scnReachRef);
#endif

    if ( gotflags && isReachable && noConnectionRequired ){
        char* ret=0;
        // size_t size = strlen(msg);
        LOG.debug("Requesting resource %s at %s:%d", url.resource, url.host, url.port);

        LOG.debug("Sending HTTP Request: %s", msg);

        // Construct some headers
        CFStringRef headerFieldName = CFSTR("Content-Type");
        CFStringRef headerFieldValue = CFSTR("application/vnd.syncml+xml");

        // Construct URL
        CFStringRef CFurl =  CFStringCreateWithCString(NULL, url.fullURL, kCFStringEncodingUTF8);
        CFURLRef myURL = CFURLCreateWithString(kCFAllocatorDefault, CFurl, NULL);

        CFStringRef requestMethod = CFSTR("POST");

        CFHTTPMessageRef httpRequest =
        CFHTTPMessageCreateRequest(kCFAllocatorDefault, requestMethod, myURL, kCFHTTPVersion1_1);
        CFStringRef useragent = CFStringCreateWithCString(NULL, getUserAgent(), kCFStringEncodingUTF8);
        CFHTTPMessageSetHeaderFieldValue(httpRequest, CFSTR("user-agent"),  useragent);
        if(!httpRequest){
            LOG.error("MacTransportAgent::sendMessage error: CFHTTPMessageCreateRequest Error.");
            setError(ERR_NETWORK_INIT, "MacTransportAgent::sendMessage error: CFHTTPMessageCreateRequest Error.");

            goto finally;
        }

        CFDataRef bodyData = CFDataCreate(kCFAllocatorDefault, (const UInt8*)msg, strlen(msg));
        if (!bodyData){
            LOG.error("MacTransportAgent::sendMessage error: CFHTTPMessageCreateRequest Error.");
            setError(ERR_NETWORK_INIT, "MacTransportAgent::sendMessage error: CFHTTPMessageCreateRequest Error.");
            goto finally;
        }
        CFHTTPMessageSetBody(httpRequest, bodyData);
        CFHTTPMessageSetHeaderFieldValue(httpRequest, headerFieldName, headerFieldValue);

        CFReadStreamRef responseStream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, httpRequest);

        //bool setProperty;
        //if we are trying to sync on a https server we have to have a trusted certificate.
        //no self signed certificates are accepted
        /*if(strcmp(url.protocol, "https")==0){
            NSDictionary *sslProperties;
            sslProperties = [NSDictionary dictionaryWithObjectsAndKeys:
                                               (NSString *)kCFStreamSocketSecurityLevelNegotiatedSSL, kCFStreamSSLLevel,
                                               kCFBooleanFalse, kCFStreamSSLAllowsAnyRoot,
                                               kCFBooleanTrue, kCFStreamSSLValidatesCertificateChain,
                                               kCFNull, kCFStreamSSLPeerName,
                                               nil];

            setProperty = CFReadStreamSetProperty( responseStream,
                                                  kCFStreamPropertySSLSettings,
                                                  sslProperties );
            [sslProperties release];
        }*/

        if (!CFReadStreamOpen(responseStream)) {//Sends request
            LOG.error("Failed to send HTTP request...");
        }

#define READ_SIZE 1000

        UInt8   buffer[READ_SIZE];
        while ( (bytesRead = CFReadStreamRead(responseStream, buffer, READ_SIZE-1)) > 0)
        {
            //   Convert what was read to a C-string
            buffer[bytesRead] = 0;
            //   Append it to the reply string
            result.append((const char*)buffer);
        }

        CFHTTPMessageRef reply = (CFHTTPMessageRef) CFReadStreamCopyProperty( responseStream, kCFStreamPropertyHTTPResponseHeader);

        // Pull the status code from the headers
        if (reply) {
            statusCode = CFHTTPMessageGetResponseStatusCode(reply);
            CFRelease(reply);
        }

        LOG.debug("Status Code: %d", statusCode);
        LOG.debug("Result: %s", result.c_str());

        switch (statusCode) {
            case 0: {
                LOG.debug("Http request successful.");

                // No errors, copy the response
                // TODO: avoid byte copy
                ret = stringdup(result.c_str());

                break;
            }
            case 200: {
                LOG.debug("Http request successful.");

                // No errors, copy the response
                // TODO: avoid byte copy
                ret = stringdup(result.c_str());

                break;
            }
            case -1: {                    // no connection (TODO: implement retry)
                setErrorF(ERR_SERVER_ERROR, "Network error in server receiving data. ");
                LOG.error("%s", getLastErrorMsg());

                break;
            }
            case 400: {                    // 400 bad request error. TODO: retry to send the message
                setErrorF(ERR_SERVER_ERROR, "HTTP server error: %d. Server failure.", statusCode);
                LOG.debug("%s", getLastErrorMsg());

                break;
            }
            case 500: {     // 500 -> out code 2052
                setErrorF(ERR_SERVER_ERROR, "HTTP server error: %d. Server failure.", statusCode);
                LOG.debug("%s", getLastErrorMsg());
                break;
            }
            case 404: {         // 404 -> out code 2060
                setErrorF(ERR_HTTP_NOT_FOUND, "HTTP request error: resource not found (status %d)", statusCode);
                LOG.debug("%s", getLastErrorMsg());
                break;
            }
            case 408: {   // 408 -> out code 2061
                setErrorF(ERR_HTTP_REQUEST_TIMEOUT, "HTTP request error: server timed out waiting for request (status %d)", statusCode);
                LOG.debug("%s", getLastErrorMsg());
                break;
            }

            default: {
                setErrorF(statusCode, "HTTP request error: status received = %d", statusCode);
                LOG.error("%s", getLastErrorMsg());
            }
        }

    finally:
        CFRelease(headerFieldName);
        CFRelease(headerFieldValue);
        CFRelease(CFurl);
        CFRelease(myURL);
        CFRelease(httpRequest);
        CFRelease(bodyData);
        CFRelease(responseStream);
        CFRelease(requestMethod);
        CFRelease(useragent);

        LOG.debug("MacTransportAgent::sendMessage end");
        return ret;
    }else{
        setErrorF(ERR_CONNECT, "Network error: the attempt to connect to the server failed -> exit");
        LOG.debug("%s", getLastErrorMsg());
        LOG.debug("MacTransportAgent::sendMessage end");
        return NULL;
    }
}

#endif

<|endoftext|>


<commit_before>//#define TWO_CAM
//#define DISPLAY
#define DEBUG_NO_SENSORS

#include <fstream>
#include "CameraLogger.h"
#include "GPSLogger.h"

#define ZMQ_CAMERALOGGER_BIND_PORT 5001 // this app will listen on this port
#define ZMQ_DIAGNOSTICS_SEND_PORT 5000 // this app will send to master on this port

#define CAMERA_DISPLAY_SKIP 3
#define NUMTHREAD_PER_BUFFER 10

SyncBuffer cam1_buff[NUMTHREAD_PER_BUFFER];
SyncBuffer cam2_buff[NUMTHREAD_PER_BUFFER];

zmq::context_t context(1);
zmq::socket_t my_commands(context, ZMQ_SUB);
zmq::socket_t send_diagnostics(context, ZMQ_PUB);

bool is_done_working = false;
bool quit_via_user_input = false;

Time currentTime(boost::posix_time::microsec_clock::local_time());
Time lastTime(currentTime);

inline void ImageCallback(Image* pImage, const void* pCallbackData,
    SyncBuffer* w_buff) {
  if (!is_done_working) {
    Image* im = new Image();
    pImage->Convert(PIXEL_FORMAT_BGR, im);
    if (!w_buff->getBuffer()->pushBack(im)) {
      boost::mutex::scoped_lock io_lock ( *(w_buff->getMutex()) );
      cerr << "Warning! Buffer full, overwriting data!" << endl;
    }
  }
}

inline void sendDiagnosticsMessage(string message) {
  zmq::message_t diag_msg_t((void *) message.c_str(), message.length(), NULL);
  send_diagnostics.send(diag_msg_t, ZMQ_NOBLOCK);
}

void ctrlC (int)
{
#ifndef DISPLAY
  //printf("\nCtrl-C detected, exit condition set to true.\n");
  //is_done_working = true;
#endif
#ifdef DISPLAY
  printf("\nCtrl-C Disabled! Use 'q' to quit instead\n");
#endif
}

int main(int argc, char** argv)
{
  using namespace boost::program_options;
  options_description desc("Allowed options");
  desc.add_options()
    ("help", "produce help message")
    ("serial,s", value<string>(), "the serial location for the gps unit")
    ("maxframes,m", value<uint64_t>(), "maximum number of frames to capture")
    ("output,o", value<string>(), "the filename for data logging");

  signal (SIGINT, ctrlC);

  string diagnostics_address = "tcp://localhost:"+boost::to_string(ZMQ_DIAGNOSTICS_SEND_PORT);
  send_diagnostics.connect(diagnostics_address.c_str());
  sleep(1);
  sendDiagnosticsMessage("WARN:Connecting to Cameras...");

  variables_map vm;
  store(parse_command_line(argc, argv, desc), vm);
  notify(vm);
  if (vm.count("help")) {
    cout << desc << endl;
    return 1;
  }
  string fname1 = "";
  string fname2 = "";
  string fnamegps = "";
  if (vm.count("output")) {
    fname1 = vm["output"].as<string>() + "1.avi";
    fname2 = vm["output"].as<string>() + "2.avi";
    fnamegps = vm["output"].as<string>() + "_gps.out";
  }
  else {
    cout << desc << endl;
    return 1;
  };

  uint64_t maxframes = -1;
  if (vm.count("maxframes")) {
    maxframes = vm["maxframes"].as<uint64_t>();
  }

#ifdef DEBUG_NO_SENSORS
  bool useGPS = false;
#else
  bool useGPS = true;
#endif
  GPSLogger gpsLogger;
  ofstream gps_output;
  if (useGPS) {
    gps_output.open(fnamegps.c_str());
    gpsLogger.Connect(vm["serial"].as<string>());
  }
  int imageWidth = 1280;
  int imageHeight = 960;

  cout << "Capturing for maximum of " << maxframes << " frames" << endl;
  cout  << "Filenames: " << fname1 << " " << fname2 << endl;

  for (int thread_num = 0; thread_num < NUMTHREAD_PER_BUFFER; thread_num++)
  {
    cam1_buff[thread_num].getBuffer()->setCapacity(1000);
    cam2_buff[thread_num].getBuffer()->setCapacity(1000);
  }

#ifndef DEBUG_NO_SENSORS
  Camera* cam1 = ConnectCamera(0); // 0 indexing
  assert(cam1 != NULL);
  RunCamera(cam1);

  Consumer<Image>* cam1_consumer[NUMTHREAD_PER_BUFFER];
  for (int thread_num = 0; thread_num < NUMTHREAD_PER_BUFFER; thread_num++) {
    stringstream sstm;
    sstm << "split_" << thread_num << "_" << fname1;
    string thread_fname = sstm.str();
    cam1_consumer[thread_num] = new Consumer<Image>(
        cam1_buff[thread_num].getBuffer(),
        thread_fname, cam1_buff[thread_num].getMutex(), 50.0f,
        imageWidth, imageHeight);
  }
#endif

#ifdef DISPLAY
  cvNamedWindow("cam1", CV_WINDOW_AUTOSIZE);
#endif

#ifdef TWO_CAM
  Camera* cam2 = ConnectCamera(1); // 0 indexing
  assert(cam2 != NULL);
  RunCamera(cam2);
  Consumer<Image>* cam2_consumer[NUMTHREAD_PER_BUFFER];
  for (int thread_num = 0; thread_num < NUMTHREAD_PER_BUFFER; thread_num++) {
    stringstream sstm;
    sstm << "split_" << thread_num << "_" << fname2;
    string thread_fname = sstm.str();
    cam2_consumer[thread_num] = new Consumer<Image>(
        cam2_buff[thread_num].getBuffer(),
        thread_fname, cam2_buff[thread_num].getMutex(), 50.0f,
        imageWidth, imageHeight);
  }
#ifdef DISPLAY
  cvNamedWindow("cam2", CV_WINDOW_AUTOSIZE);
#endif //DISPLAY
#endif //TWO_CAM

  IplImage* img = cvCreateImage(cvSize(imageWidth, imageHeight), IPL_DEPTH_8U, 3);
  string lastValidGPSPacket;

  //// setup ZMQ communication
  string bind_address = "tcp://*:"+boost::to_string(ZMQ_CAMERALOGGER_BIND_PORT);
  cout << "binding to " << bind_address << endl;
  my_commands.bind("tcp://*:5001");
  my_commands.setsockopt(ZMQ_SUBSCRIBE, NULL, 0);
  cout << "binding successful" << endl;

#ifdef DEBUG_NO_SENSORS
  img = cvLoadImage("/home/smart/sail-car-log/cameralogger/xkcd.png");
  lastValidGPSPacket="#MARK1PVAA,USB1,0,92.0,EXACT,1753,238273.050,00000000,0000,470;1753,238273.050000025,37.856359728,-122.494864165,110.390118713,16.041177523,-24.789919285,-1.752024973,-3.954175540,4.393638450,32.292000751,INS_SOLUTION_GOOD*016857cc";
#endif

  // start GPS Trigger
  if (useGPS) gpsLogger.Run();

  uint64_t numframes = 0;
  uint64_t lastframes = 0;
  ///////// main loop
  while (!is_done_working) {
    numframes++;
    if (numframes > maxframes) {
      is_done_working = true;
    }
    try {
      zmq::message_t command_msg;
      if (my_commands.recv(&command_msg, ZMQ_NOBLOCK) == true) {
        string command((const char*)command_msg.data(), command_msg.size());
        if (command.compare("TERMINATE") == 0) {
          // properly close the application
          is_done_working = true;
          quit_via_user_input = true;
        }
        else if (command.compare("LASTCAMERADATA") == 0) {
          // transmit the camera data over
        }
        else if (command.compare("LASTGPSDATA") == 0) {
          // transmit the last known GPS log over
        }
      }
    } catch (const zmq::error_t&e) {}

#ifndef DEBUG_NO_SENSORS
    Image image;
    cam1->RetrieveBuffer(&image);
    ImageCallback(&image, NULL, &cam1_buff[numframes % NUMTHREAD_PER_BUFFER]);

    Image cimage;
    if (numframes % CAMERA_DISPLAY_SKIP == 0) {
      image.Convert(PIXEL_FORMAT_BGR, &cimage);
      convertToCV(&cimage, img);
      #ifdef DISPLAY
      show(img, "cam1");
      #endif //DISPLAY
    }
#endif //DEBUG_NO_SENSORS

#ifdef TWO_CAM
    cam2->RetrieveBuffer(&image);
    ImageCallback(&image, NULL, &cam2_buff[numframes % NUMTHREAD_PER_BUFFER]);
    if (numframes % CAMERA_DISPLAY_SKIP == 0) {
      image.Convert(PIXEL_FORMAT_BGR, &cimage);
      convertToCV(&cimage, img);
      #ifdef DISPLAY
      show(img, "cam2");
      #endif //DISPLAY
    }
#endif // TWO_CAM

#ifdef DISPLAY
    char r = cvWaitKey(1);
    if (r == 'q') {
      is_done_working = true;
      quit_via_user_input = true;
    }
#endif //DISPLAY

    if (useGPS) {
      GPSLogger::GPSPacketType packet = gpsLogger.getPacket();
      int GPSPacketSuccess = boost::get<0>(packet);
      if (GPSPacketSuccess > 0) {
        lastValidGPSPacket = boost::get<1>(packet);
        gps_output << lastValidGPSPacket << endl;
      } else {
        sendDiagnosticsMessage("WARN:Bad GPS Packet");
      }

    }

    currentTime = Time(boost::posix_time::microsec_clock::local_time());
    if ((currentTime - lastTime).total_milliseconds() > 1000) {
      string captureRateMsg = "INFOCAPTURERATE:" + boost::to_string(numframes-lastframes);
      sendDiagnosticsMessage(captureRateMsg);

      int queue_size = 0;
      for (int thread_num = 0; thread_num < NUMTHREAD_PER_BUFFER; thread_num++)
      {
        queue_size += cam1_buff[thread_num].getBuffer()->getSize();
        queue_size += cam2_buff[thread_num].getBuffer()->getSize();
      }

      string bufferSizeMsg = "INFOBUFFERSIZE:" + boost::to_string(queue_size);
      sendDiagnosticsMessage(bufferSizeMsg);

      // encode last image for transmission
      Mat lastCameraImage(img);
      vector<uchar> lastCameraImageBuf; string lastCameraImageMsg;
      resize(lastCameraImage, lastCameraImage, Size(320,240));
      imencode(".png", lastCameraImage, lastCameraImageBuf);
      lastCameraImageMsg = string(lastCameraImageBuf.begin(), lastCameraImageBuf.end());
      lastCameraImageMsg = "CAM:" + lastCameraImageMsg;
      sendDiagnosticsMessage(lastCameraImageMsg);

      GPSRecord record(lastValidGPSPacket);
      if (record.isValid()) {
        std::ostringstream lat;
        lat << std::fixed << std::setprecision(8);
        lat << record.latitude;
        std::ostringstream lon;
        lon << std::fixed << std::setprecision(8);
        lon << record.longitude;
        string gpsMsg = "GPS:" + lat.str() + "," + lon.str();
        sendDiagnosticsMessage(gpsMsg);
      }

      lastTime = currentTime;
      lastframes = numframes;
    }
#ifdef DEBUG_NO_SENSORS
    usleep(200);
#endif
  }
  cout << "numframes = " << numframes << endl;

  /////// cleanup
  if (useGPS) gpsLogger.Close();
#ifdef DISPLAY
  cvDestroyWindow("cam1");
  cvDestroyWindow("cam2");
#endif
#ifndef DEBUG_NO_SENSORS
  for (int thread_num = 0; thread_num < NUMTHREAD_PER_BUFFER; thread_num++) {
    cam1_consumer[thread_num]->stop();
    delete cam1_consumer[thread_num];
  }
  CloseCamera(cam1);
  delete cam1;
#endif
#ifdef TWO_CAM
  for (int thread_num = 0; thread_num < NUMTHREAD_PER_BUFFER; thread_num++) {
    cam2_consumer[thread_num]->stop();
    delete cam2_consumer[thread_num];
  }
  CloseCamera(cam2);
  delete cam2;
#endif
  if (quit_via_user_input) return 1;
  return 0;
}
<commit_msg>more warnings<commit_after>//#define TWO_CAM
//#define DISPLAY
#define DEBUG_NO_SENSORS

#include <fstream>
#include "CameraLogger.h"
#include "GPSLogger.h"

#define ZMQ_CAMERALOGGER_BIND_PORT 5001 // this app will listen on this port
#define ZMQ_DIAGNOSTICS_SEND_PORT 5000 // this app will send to master on this port

#define CAMERA_DISPLAY_SKIP 3
#define NUMTHREAD_PER_BUFFER 10

SyncBuffer cam1_buff[NUMTHREAD_PER_BUFFER];
SyncBuffer cam2_buff[NUMTHREAD_PER_BUFFER];

zmq::context_t context(1);
zmq::socket_t my_commands(context, ZMQ_SUB);
zmq::socket_t send_diagnostics(context, ZMQ_PUB);

bool is_done_working = false;
bool quit_via_user_input = false;

Time currentTime(boost::posix_time::microsec_clock::local_time());
Time lastTime(currentTime);

inline void ImageCallback(Image* pImage, const void* pCallbackData,
    SyncBuffer* w_buff) {
  if (!is_done_working) {
    Image* im = new Image();
    pImage->Convert(PIXEL_FORMAT_BGR, im);
    if (!w_buff->getBuffer()->pushBack(im)) {
      boost::mutex::scoped_lock io_lock ( *(w_buff->getMutex()) );
      cerr << "Warning! Buffer full, overwriting data!" << endl;
    }
  }
}

inline void sendDiagnosticsMessage(string message) {
  zmq::message_t diag_msg_t((void *) message.c_str(), message.length(), NULL);
  send_diagnostics.send(diag_msg_t, ZMQ_NOBLOCK);
}

void ctrlC (int)
{
#ifndef DISPLAY
  //printf("\nCtrl-C detected, exit condition set to true.\n");
  //is_done_working = true;
#endif
#ifdef DISPLAY
  printf("\nCtrl-C Disabled! Use 'q' to quit instead\n");
#endif
}

int main(int argc, char** argv)
{
  using namespace boost::program_options;
  options_description desc("Allowed options");
  desc.add_options()
    ("help", "produce help message")
    ("serial,s", value<string>(), "the serial location for the gps unit")
    ("maxframes,m", value<uint64_t>(), "maximum number of frames to capture")
    ("output,o", value<string>(), "the filename for data logging");

  signal (SIGINT, ctrlC);

  string diagnostics_address = "tcp://localhost:"+boost::to_string(ZMQ_DIAGNOSTICS_SEND_PORT);
  send_diagnostics.connect(diagnostics_address.c_str());
  sleep(1);
  sendDiagnosticsMessage("WARN:Connecting to Cameras...");

  variables_map vm;
  store(parse_command_line(argc, argv, desc), vm);
  notify(vm);
  if (vm.count("help")) {
    cout << desc << endl;
    return 1;
  }
  string fname1 = "";
  string fname2 = "";
  string fnamegps = "";
  if (vm.count("output")) {
    fname1 = vm["output"].as<string>() + "1.avi";
    fname2 = vm["output"].as<string>() + "2.avi";
    fnamegps = vm["output"].as<string>() + "_gps.out";
  }
  else {
    cout << desc << endl;
    return 1;
  };

  uint64_t maxframes = -1;
  if (vm.count("maxframes")) {
    maxframes = vm["maxframes"].as<uint64_t>();
  }

#ifdef DEBUG_NO_SENSORS
  bool useGPS = false;
#else
  bool useGPS = true;
#endif
  GPSLogger gpsLogger;
  ofstream gps_output;
  if (useGPS) {
    gps_output.open(fnamegps.c_str());
    gpsLogger.Connect(vm["serial"].as<string>());
  }
  int imageWidth = 1280;
  int imageHeight = 960;

  cout << "Capturing for maximum of " << maxframes << " frames" << endl;
  cout  << "Filenames: " << fname1 << " " << fname2 << endl;

  for (int thread_num = 0; thread_num < NUMTHREAD_PER_BUFFER; thread_num++)
  {
    cam1_buff[thread_num].getBuffer()->setCapacity(1000);
    cam2_buff[thread_num].getBuffer()->setCapacity(1000);
  }

#ifndef DEBUG_NO_SENSORS
  Camera* cam1 = ConnectCamera(0); // 0 indexing
  assert(cam1 != NULL);
  RunCamera(cam1);

  Consumer<Image>* cam1_consumer[NUMTHREAD_PER_BUFFER];
  for (int thread_num = 0; thread_num < NUMTHREAD_PER_BUFFER; thread_num++) {
    stringstream sstm;
    sstm << "split_" << thread_num << "_" << fname1;
    string thread_fname = sstm.str();
    cam1_consumer[thread_num] = new Consumer<Image>(
        cam1_buff[thread_num].getBuffer(),
        thread_fname, cam1_buff[thread_num].getMutex(), 50.0f,
        imageWidth, imageHeight);
  }
#endif

#ifdef DISPLAY
  cvNamedWindow("cam1", CV_WINDOW_AUTOSIZE);
#endif

#ifdef TWO_CAM
  Camera* cam2 = ConnectCamera(1); // 0 indexing
  assert(cam2 != NULL);
  RunCamera(cam2);
  Consumer<Image>* cam2_consumer[NUMTHREAD_PER_BUFFER];
  for (int thread_num = 0; thread_num < NUMTHREAD_PER_BUFFER; thread_num++) {
    stringstream sstm;
    sstm << "split_" << thread_num << "_" << fname2;
    string thread_fname = sstm.str();
    cam2_consumer[thread_num] = new Consumer<Image>(
        cam2_buff[thread_num].getBuffer(),
        thread_fname, cam2_buff[thread_num].getMutex(), 50.0f,
        imageWidth, imageHeight);
  }
#ifdef DISPLAY
  cvNamedWindow("cam2", CV_WINDOW_AUTOSIZE);
#endif //DISPLAY
#endif //TWO_CAM

  IplImage* img = cvCreateImage(cvSize(imageWidth, imageHeight), IPL_DEPTH_8U, 3);
  string lastValidGPSPacket;

  //// setup ZMQ communication
  string bind_address = "tcp://*:"+boost::to_string(ZMQ_CAMERALOGGER_BIND_PORT);
  cout << "binding to " << bind_address << endl;
  my_commands.bind("tcp://*:5001");
  my_commands.setsockopt(ZMQ_SUBSCRIBE, NULL, 0);
  cout << "binding successful" << endl;

#ifdef DEBUG_NO_SENSORS
  img = cvLoadImage("/home/smart/sail-car-log/cameralogger/xkcd.png");
  lastValidGPSPacket="#MARK1PVAA,USB1,0,92.0,EXACT,1753,238273.050,00000000,0000,470;1753,238273.050000025,37.856359728,-122.494864165,110.390118713,16.041177523,-24.789919285,-1.752024973,-3.954175540,4.393638450,32.292000751,INS_SOLUTION_GOOD*016857cc";
#endif

  // start GPS Trigger
  sendDiagnosticsMessage("WARN:Connecting to GPS...");
  if (useGPS) gpsLogger.Run();

  uint64_t numframes = 0;
  uint64_t lastframes = 0;
  ///////// main loop
  while (!is_done_working) {
    numframes++;
    if (numframes > maxframes) {
      is_done_working = true;
    }
    try {
      zmq::message_t command_msg;
      if (my_commands.recv(&command_msg, ZMQ_NOBLOCK) == true) {
        string command((const char*)command_msg.data(), command_msg.size());
        if (command.compare("TERMINATE") == 0) {
          // properly close the application
          is_done_working = true;
          quit_via_user_input = true;
        }
        else if (command.compare("LASTCAMERADATA") == 0) {
          // transmit the camera data over
        }
        else if (command.compare("LASTGPSDATA") == 0) {
          // transmit the last known GPS log over
        }
      }
    } catch (const zmq::error_t&e) {}

#ifndef DEBUG_NO_SENSORS
    Image image;
    cam1->RetrieveBuffer(&image);
    ImageCallback(&image, NULL, &cam1_buff[numframes % NUMTHREAD_PER_BUFFER]);

    Image cimage;
    if (numframes % CAMERA_DISPLAY_SKIP == 0) {
      image.Convert(PIXEL_FORMAT_BGR, &cimage);
      convertToCV(&cimage, img);
      #ifdef DISPLAY
      show(img, "cam1");
      #endif //DISPLAY
    }
#endif //DEBUG_NO_SENSORS

#ifdef TWO_CAM
    cam2->RetrieveBuffer(&image);
    ImageCallback(&image, NULL, &cam2_buff[numframes % NUMTHREAD_PER_BUFFER]);
    if (numframes % CAMERA_DISPLAY_SKIP == 0) {
      image.Convert(PIXEL_FORMAT_BGR, &cimage);
      convertToCV(&cimage, img);
      #ifdef DISPLAY
      show(img, "cam2");
      #endif //DISPLAY
    }
#endif // TWO_CAM

#ifdef DISPLAY
    char r = cvWaitKey(1);
    if (r == 'q') {
      is_done_working = true;
      quit_via_user_input = true;
    }
#endif //DISPLAY

    if (useGPS) {
      GPSLogger::GPSPacketType packet = gpsLogger.getPacket();
      int GPSPacketSuccess = boost::get<0>(packet);
      if (GPSPacketSuccess > 0) {
        lastValidGPSPacket = boost::get<1>(packet);
        gps_output << lastValidGPSPacket << endl;
      } else {
        sendDiagnosticsMessage("WARN:Bad GPS Packet");
      }

    }

    currentTime = Time(boost::posix_time::microsec_clock::local_time());
    if ((currentTime - lastTime).total_milliseconds() > 1000) {
      string captureRateMsg = "INFOCAPTURERATE:" + boost::to_string(numframes-lastframes);
      sendDiagnosticsMessage(captureRateMsg);

      int queue_size = 0;
      for (int thread_num = 0; thread_num < NUMTHREAD_PER_BUFFER; thread_num++)
      {
        queue_size += cam1_buff[thread_num].getBuffer()->getSize();
        queue_size += cam2_buff[thread_num].getBuffer()->getSize();
      }

      string bufferSizeMsg = "INFOBUFFERSIZE:" + boost::to_string(queue_size);
      sendDiagnosticsMessage(bufferSizeMsg);

      // encode last image for transmission
      Mat lastCameraImage(img);
      vector<uchar> lastCameraImageBuf; string lastCameraImageMsg;
      resize(lastCameraImage, lastCameraImage, Size(320,240));
      imencode(".png", lastCameraImage, lastCameraImageBuf);
      lastCameraImageMsg = string(lastCameraImageBuf.begin(), lastCameraImageBuf.end());
      lastCameraImageMsg = "CAM:" + lastCameraImageMsg;
      sendDiagnosticsMessage(lastCameraImageMsg);

      GPSRecord record(lastValidGPSPacket);
      if (record.isValid()) {
        std::ostringstream lat;
        lat << std::fixed << std::setprecision(8);
        lat << record.latitude;
        std::ostringstream lon;
        lon << std::fixed << std::setprecision(8);
        lon << record.longitude;
        string gpsMsg = "GPS:" + lat.str() + "," + lon.str();
        sendDiagnosticsMessage(gpsMsg);
      }

      lastTime = currentTime;
      lastframes = numframes;
    }
#ifdef DEBUG_NO_SENSORS
    usleep(200);
#endif
  }
  cout << "numframes = " << numframes << endl;

  /////// cleanup
  sendDiagnosticsMessage("WARN:Shutting Down GPS...");
  if (useGPS) gpsLogger.Close();
#ifdef DISPLAY
  cvDestroyWindow("cam1");
  cvDestroyWindow("cam2");
  sendDiagnosticsMessage("WARN:Shutting Down Cameras...");
#endif
#ifndef DEBUG_NO_SENSORS
  for (int thread_num = 0; thread_num < NUMTHREAD_PER_BUFFER; thread_num++) {
    cam1_consumer[thread_num]->stop();
    delete cam1_consumer[thread_num];
  }
  CloseCamera(cam1);
  delete cam1;
#endif
#ifdef TWO_CAM
  for (int thread_num = 0; thread_num < NUMTHREAD_PER_BUFFER; thread_num++) {
    cam2_consumer[thread_num]->stop();
    delete cam2_consumer[thread_num];
  }
  CloseCamera(cam2);
  delete cam2;
#endif
  if (quit_via_user_input) return 1;
  return 0;
}
<|endoftext|>