<commit_before>/****************************************************************************
 *
 *   Copyright (c) 2013-2016 PX4 Development Team. 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.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "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 THE
 * COPYRIGHT OWNER 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.
 *
 ****************************************************************************/

/**
 * @file airspeed_calibration.cpp
 * Airspeed sensor calibration routine
 */

#include "airspeed_calibration.h"
#include "calibration_messages.h"
#include "calibration_routines.h"
#include "commander_helper.h"

#include <px4_defines.h>
#include <px4_posix.h>
#include <px4_time.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
#include <cmath>
#include <drivers/drv_hrt.h>
#include <drivers/drv_airspeed.h>
#include <uORB/topics/differential_pressure.h>
#include <systemlib/mavlink_log.h>
#include <systemlib/param/param.h>
#include <systemlib/err.h>
#include <systemlib/airspeed.h>

static const char *sensor_name = "dpress";

static void feedback_calibration_failed(orb_advert_t *mavlink_log_pub)
{
	sleep(5);
	calibration_log_critical(mavlink_log_pub, CAL_QGC_FAILED_MSG, sensor_name);
}

int do_airspeed_calibration(orb_advert_t *mavlink_log_pub)
{
	int result = PX4_OK;
	unsigned calibration_counter = 0;
	const unsigned maxcount = 2400;

	/* give directions */
	calibration_log_info(mavlink_log_pub, CAL_QGC_STARTED_MSG, sensor_name);

	const unsigned calibration_count = (maxcount * 2) / 3;

	int diff_pres_sub = orb_subscribe(ORB_ID(differential_pressure));
	struct differential_pressure_s diff_pres;

	float diff_pres_offset = 0.0f;

	/* Reset sensor parameters */
	struct airspeed_scale airscale = {
		diff_pres_offset,
		1.0f,
	};

	bool paramreset_successful = false;
	int  fd = px4_open(AIRSPEED0_DEVICE_PATH, 0);

	if (fd > 0) {
		if (PX4_OK == px4_ioctl(fd, AIRSPEEDIOCSSCALE, (long unsigned int)&airscale)) {
			paramreset_successful = true;

		} else {
			calibration_log_critical(mavlink_log_pub, "[cal] airspeed offset zero failed");
		}

		px4_close(fd);
	}

	int cancel_sub = calibrate_cancel_subscribe();

	if (!paramreset_successful) {

		/* only warn if analog scaling is zero */
		float analog_scaling = 0.0f;
		param_get(param_find("SENS_DPRES_ANSC"), &(analog_scaling));
		if (fabsf(analog_scaling) < 0.1f) {
			calibration_log_critical(mavlink_log_pub, "[cal] No airspeed sensor, see http://px4.io/help/aspd");
			goto error_return;
		}

		/* set scaling offset parameter */
		if (param_set(param_find("SENS_DPRES_OFF"), &(diff_pres_offset))) {
			calibration_log_critical(mavlink_log_pub, CAL_ERROR_SET_PARAMS_MSG, 1);
			goto error_return;
		}
	}

	calibration_log_critical(mavlink_log_pub, "[cal] Ensure sensor is not measuring wind");
	usleep(500 * 1000);

	while (calibration_counter < calibration_count) {

		if (calibrate_cancel_check(mavlink_log_pub, cancel_sub)) {
			goto error_return;
		}

		/* wait blocking for new data */
		px4_pollfd_struct_t fds[1];
		fds[0].fd = diff_pres_sub;
		fds[0].events = POLLIN;

		int poll_ret = px4_poll(fds, 1, 1000);

		if (poll_ret) {
			orb_copy(ORB_ID(differential_pressure), diff_pres_sub, &diff_pres);

			diff_pres_offset += diff_pres.differential_pressure_raw_pa;
			calibration_counter++;

			/* any differential pressure failure a reason to abort */
			if (diff_pres.error_count != 0) {
				calibration_log_critical(mavlink_log_pub, "[cal] airspeed error count non zero");
				feedback_calibration_failed(mavlink_log_pub);
				goto error_return;
			}

			if (calibration_counter % (calibration_count / 20) == 0) {
				calibration_log_info(mavlink_log_pub, CAL_QGC_PROGRESS_MSG, (calibration_counter * 80) / calibration_count);
			}

		} else if (poll_ret == 0) {
			/* any poll failure for 1s is a reason to abort */
			feedback_calibration_failed(mavlink_log_pub);
			goto error_return;
		}
	}

	diff_pres_offset = diff_pres_offset / calibration_count;

	if (PX4_ISFINITE(diff_pres_offset)) {

		int  fd_scale = px4_open(AIRSPEED0_DEVICE_PATH, 0);
		airscale.offset_pa = diff_pres_offset;
		if (fd_scale > 0) {
			if (PX4_OK != px4_ioctl(fd_scale, AIRSPEEDIOCSSCALE, (long unsigned int)&airscale)) {
				calibration_log_critical(mavlink_log_pub, "[cal] airspeed offset update failed");
			}

			px4_close(fd_scale);
		}

		if (param_set(param_find("SENS_DPRES_OFF"), &(diff_pres_offset))) {
			calibration_log_critical(mavlink_log_pub, CAL_ERROR_SET_PARAMS_MSG, 1);
			goto error_return;
		}

		/* auto-save to EEPROM */
		int save_ret = param_save_default();

		if (save_ret != 0) {
			warn("WARNING: auto-save of params to storage failed");
			calibration_log_critical(mavlink_log_pub, CAL_ERROR_SAVE_PARAMS_MSG);
			goto error_return;
		}

	} else {
		feedback_calibration_failed(mavlink_log_pub);
		goto error_return;
	}

	calibration_log_info(mavlink_log_pub, "[cal] Offset of %d Pascal", (int)diff_pres_offset);

	/* wait 500 ms to ensure parameter propagated through the system */
	usleep(500 * 1000);

	calibration_log_critical(mavlink_log_pub, "[cal] Blow across front of pitot without touching");

	calibration_counter = 0;

	/* just take a few samples and make sure pitot tubes are not reversed, timeout after ~30 seconds */
	while (calibration_counter < maxcount) {

		if (calibrate_cancel_check(mavlink_log_pub, cancel_sub)) {
			goto error_return;
		}

		/* wait blocking for new data */
		px4_pollfd_struct_t fds[1];
		fds[0].fd = diff_pres_sub;
		fds[0].events = POLLIN;

		int poll_ret = px4_poll(fds, 1, 1000);

		if (poll_ret) {
			orb_copy(ORB_ID(differential_pressure), diff_pres_sub, &diff_pres);

			calibration_counter++;

			if (fabsf(diff_pres.differential_pressure_raw_pa) < 50.0f) {
				if (calibration_counter % 500 == 0) {
					calibration_log_info(mavlink_log_pub, "[cal] Create air pressure! (got %d, wanted: 50 Pa)",
						(int)diff_pres.differential_pressure_raw_pa);
				}
				continue;
			}

			/* do not allow negative values */
			if (diff_pres.differential_pressure_raw_pa < 0.0f) {
				calibration_log_info(mavlink_log_pub, "[cal] Negative pressure difference detected (%d Pa)",
						(int)diff_pres.differential_pressure_raw_pa);
				calibration_log_info(mavlink_log_pub, "[cal] Swap static and dynamic ports!");

				/* the user setup is wrong, wipe the calibration to force a proper re-calibration */

				diff_pres_offset = 0.0f;
				if (param_set(param_find("SENS_DPRES_OFF"), &(diff_pres_offset))) {
					calibration_log_critical(mavlink_log_pub, CAL_ERROR_SET_PARAMS_MSG, 1);
					goto error_return;
				}

				/* save */
				calibration_log_info(mavlink_log_pub, CAL_QGC_PROGRESS_MSG, 0);
				(void)param_save_default();

				feedback_calibration_failed(mavlink_log_pub);
				goto error_return;

			} else {
				calibration_log_info(mavlink_log_pub, "[cal] Positive pressure: OK (%d Pa)",
					(int)diff_pres.differential_pressure_raw_pa);
				break;
			}

		} else if (poll_ret == 0) {
			/* any poll failure for 1s is a reason to abort */
			feedback_calibration_failed(mavlink_log_pub);
			goto error_return;
		}
	}

	if (calibration_counter == maxcount) {
		feedback_calibration_failed(mavlink_log_pub);
		goto error_return;
	}

	calibration_log_info(mavlink_log_pub, CAL_QGC_PROGRESS_MSG, 100);

	calibration_log_info(mavlink_log_pub, CAL_QGC_DONE_MSG, sensor_name);
	tune_neutral(true);

	/* Wait 2sec for the airflow to stop and ensure the driver filter has caught up, otherwise
	 * the followup preflight checks might fail. */
	usleep(2e6);

normal_return:
	calibrate_cancel_unsubscribe(cancel_sub);
	px4_close(diff_pres_sub);

	// This give a chance for the log messages to go out of the queue before someone else stomps on then
	sleep(1);

	return result;

error_return:
	result = PX4_ERROR;
	goto normal_return;
}
<commit_msg>airspeed cal more descriptive error message (#6324)<commit_after>/****************************************************************************
 *
 *   Copyright (c) 2013-2016 PX4 Development Team. 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.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "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 THE
 * COPYRIGHT OWNER 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.
 *
 ****************************************************************************/

/**
 * @file airspeed_calibration.cpp
 * Airspeed sensor calibration routine
 */

#include "airspeed_calibration.h"
#include "calibration_messages.h"
#include "calibration_routines.h"
#include "commander_helper.h"

#include <px4_defines.h>
#include <px4_posix.h>
#include <px4_time.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
#include <cmath>
#include <drivers/drv_hrt.h>
#include <drivers/drv_airspeed.h>
#include <uORB/topics/differential_pressure.h>
#include <systemlib/mavlink_log.h>
#include <systemlib/param/param.h>
#include <systemlib/err.h>
#include <systemlib/airspeed.h>

static const char *sensor_name = "airspeed";

static void feedback_calibration_failed(orb_advert_t *mavlink_log_pub)
{
	sleep(5);
	calibration_log_critical(mavlink_log_pub, CAL_QGC_FAILED_MSG, sensor_name);
}

int do_airspeed_calibration(orb_advert_t *mavlink_log_pub)
{
	int result = PX4_OK;
	unsigned calibration_counter = 0;
	const unsigned maxcount = 2400;

	/* give directions */
	calibration_log_info(mavlink_log_pub, CAL_QGC_STARTED_MSG, sensor_name);

	const unsigned calibration_count = (maxcount * 2) / 3;

	int diff_pres_sub = orb_subscribe(ORB_ID(differential_pressure));
	struct differential_pressure_s diff_pres;

	float diff_pres_offset = 0.0f;

	/* Reset sensor parameters */
	struct airspeed_scale airscale = {
		diff_pres_offset,
		1.0f,
	};

	bool paramreset_successful = false;
	int  fd = px4_open(AIRSPEED0_DEVICE_PATH, 0);

	if (fd > 0) {
		if (PX4_OK == px4_ioctl(fd, AIRSPEEDIOCSSCALE, (long unsigned int)&airscale)) {
			paramreset_successful = true;

		} else {
			calibration_log_critical(mavlink_log_pub, "[cal] airspeed offset zero failed");
		}

		px4_close(fd);
	}

	int cancel_sub = calibrate_cancel_subscribe();

	if (!paramreset_successful) {

		/* only warn if analog scaling is zero */
		float analog_scaling = 0.0f;
		param_get(param_find("SENS_DPRES_ANSC"), &(analog_scaling));
		if (fabsf(analog_scaling) < 0.1f) {
			calibration_log_critical(mavlink_log_pub, "[cal] No airspeed sensor, see http://px4.io/help/aspd");
			goto error_return;
		}

		/* set scaling offset parameter */
		if (param_set(param_find("SENS_DPRES_OFF"), &(diff_pres_offset))) {
			calibration_log_critical(mavlink_log_pub, CAL_ERROR_SET_PARAMS_MSG, 1);
			goto error_return;
		}
	}

	calibration_log_critical(mavlink_log_pub, "[cal] Ensure sensor is not measuring wind");
	usleep(500 * 1000);

	while (calibration_counter < calibration_count) {

		if (calibrate_cancel_check(mavlink_log_pub, cancel_sub)) {
			goto error_return;
		}

		/* wait blocking for new data */
		px4_pollfd_struct_t fds[1];
		fds[0].fd = diff_pres_sub;
		fds[0].events = POLLIN;

		int poll_ret = px4_poll(fds, 1, 1000);

		if (poll_ret) {
			orb_copy(ORB_ID(differential_pressure), diff_pres_sub, &diff_pres);

			diff_pres_offset += diff_pres.differential_pressure_raw_pa;
			calibration_counter++;

			/* any differential pressure failure a reason to abort */
			if (diff_pres.error_count != 0) {
				calibration_log_critical(mavlink_log_pub, "[cal] Airspeed sensor is reporting errors (%d)", diff_pres.error_count);
				calibration_log_critical(mavlink_log_pub, "[cal] Check your wiring before trying again");
				feedback_calibration_failed(mavlink_log_pub);
				goto error_return;
			}

			if (calibration_counter % (calibration_count / 20) == 0) {
				calibration_log_info(mavlink_log_pub, CAL_QGC_PROGRESS_MSG, (calibration_counter * 80) / calibration_count);
			}

		} else if (poll_ret == 0) {
			/* any poll failure for 1s is a reason to abort */
			feedback_calibration_failed(mavlink_log_pub);
			goto error_return;
		}
	}

	diff_pres_offset = diff_pres_offset / calibration_count;

	if (PX4_ISFINITE(diff_pres_offset)) {

		int  fd_scale = px4_open(AIRSPEED0_DEVICE_PATH, 0);
		airscale.offset_pa = diff_pres_offset;
		if (fd_scale > 0) {
			if (PX4_OK != px4_ioctl(fd_scale, AIRSPEEDIOCSSCALE, (long unsigned int)&airscale)) {
				calibration_log_critical(mavlink_log_pub, "[cal] airspeed offset update failed");
			}

			px4_close(fd_scale);
		}

		if (param_set(param_find("SENS_DPRES_OFF"), &(diff_pres_offset))) {
			calibration_log_critical(mavlink_log_pub, CAL_ERROR_SET_PARAMS_MSG, 1);
			goto error_return;
		}

		/* auto-save to EEPROM */
		int save_ret = param_save_default();

		if (save_ret != 0) {
			warn("WARNING: auto-save of params to storage failed");
			calibration_log_critical(mavlink_log_pub, CAL_ERROR_SAVE_PARAMS_MSG);
			goto error_return;
		}

	} else {
		feedback_calibration_failed(mavlink_log_pub);
		goto error_return;
	}

	calibration_log_info(mavlink_log_pub, "[cal] Offset of %d Pascal", (int)diff_pres_offset);

	/* wait 500 ms to ensure parameter propagated through the system */
	usleep(500 * 1000);

	calibration_log_critical(mavlink_log_pub, "[cal] Blow across front of pitot without touching");

	calibration_counter = 0;

	/* just take a few samples and make sure pitot tubes are not reversed, timeout after ~30 seconds */
	while (calibration_counter < maxcount) {

		if (calibrate_cancel_check(mavlink_log_pub, cancel_sub)) {
			goto error_return;
		}

		/* wait blocking for new data */
		px4_pollfd_struct_t fds[1];
		fds[0].fd = diff_pres_sub;
		fds[0].events = POLLIN;

		int poll_ret = px4_poll(fds, 1, 1000);

		if (poll_ret) {
			orb_copy(ORB_ID(differential_pressure), diff_pres_sub, &diff_pres);

			calibration_counter++;

			if (fabsf(diff_pres.differential_pressure_raw_pa) < 50.0f) {
				if (calibration_counter % 500 == 0) {
					calibration_log_info(mavlink_log_pub, "[cal] Create air pressure! (got %d, wanted: 50 Pa)",
						(int)diff_pres.differential_pressure_raw_pa);
				}
				continue;
			}

			/* do not allow negative values */
			if (diff_pres.differential_pressure_raw_pa < 0.0f) {
				calibration_log_info(mavlink_log_pub, "[cal] Negative pressure difference detected (%d Pa)",
						(int)diff_pres.differential_pressure_raw_pa);
				calibration_log_info(mavlink_log_pub, "[cal] Swap static and dynamic ports!");

				/* the user setup is wrong, wipe the calibration to force a proper re-calibration */

				diff_pres_offset = 0.0f;
				if (param_set(param_find("SENS_DPRES_OFF"), &(diff_pres_offset))) {
					calibration_log_critical(mavlink_log_pub, CAL_ERROR_SET_PARAMS_MSG, 1);
					goto error_return;
				}

				/* save */
				calibration_log_info(mavlink_log_pub, CAL_QGC_PROGRESS_MSG, 0);
				(void)param_save_default();

				feedback_calibration_failed(mavlink_log_pub);
				goto error_return;

			} else {
				calibration_log_info(mavlink_log_pub, "[cal] Positive pressure: OK (%d Pa)",
					(int)diff_pres.differential_pressure_raw_pa);
				break;
			}

		} else if (poll_ret == 0) {
			/* any poll failure for 1s is a reason to abort */
			feedback_calibration_failed(mavlink_log_pub);
			goto error_return;
		}
	}

	if (calibration_counter == maxcount) {
		feedback_calibration_failed(mavlink_log_pub);
		goto error_return;
	}

	calibration_log_info(mavlink_log_pub, CAL_QGC_PROGRESS_MSG, 100);

	calibration_log_info(mavlink_log_pub, CAL_QGC_DONE_MSG, sensor_name);
	tune_neutral(true);

	/* Wait 2sec for the airflow to stop and ensure the driver filter has caught up, otherwise
	 * the followup preflight checks might fail. */
	usleep(2e6);

normal_return:
	calibrate_cancel_unsubscribe(cancel_sub);
	px4_close(diff_pres_sub);

	// This give a chance for the log messages to go out of the queue before someone else stomps on then
	sleep(1);

	return result;

error_return:
	result = PX4_ERROR;
	goto normal_return;
}
<|endoftext|>


<commit_before>/////////////////////////////////////////////////////////////////////////
// $Id: eth_linux.cc,v 1.20 2004/10/07 17:38:03 vruppert Exp $
/////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2001  MandrakeSoft S.A.
//
//    MandrakeSoft S.A.
//    43, rue d'Aboukir
//    75002 Paris - France
//    http://www.linux-mandrake.com/
//    http://www.mandrakesoft.com/
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library 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
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

// Peter Grehan (grehan@iprg.nokia.com) coded all of this
// NE2000/ether stuff.

// eth_linux.cc - A Linux socket filter adaptation of the FreeBSD BPF driver
// <splite@purdue.edu> 21 June 2001
//
// Problems and limitations:
//   - packets cannot be sent from BOCHS to the host
//   - Linux kernel sometimes gets network watchdog timeouts under emulation
//   - author doesn't know C++
//
//   The config line in .bochsrc should look something like:
//
//  ne2k: ioaddr=0x280, irq=10, mac=00:a:b:c:1:2, ethmod=linux, ethdev=eth0
//

// Define BX_PLUGGABLE in files that can be compiled into plugins.  For
// platforms that require a special tag on exported symbols, BX_PLUGGABLE
// is used to know when we are exporting symbols and when we are importing.
#define BX_PLUGGABLE

#include "iodev.h"
#if BX_NETWORKING && defined (ETH_LINUX)

#include "eth.h"

#define LOG_THIS bx_devices.pluginNE2kDevice->

extern "C" {
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netpacket/packet.h>
#include <netinet/in.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <linux/types.h>
#include <linux/filter.h>
};

#define BX_PACKET_POLL  1000    // Poll for a frame every 1000 usecs

// template filter for a unicast mac address and all
// multicast/broadcast frames
static const struct sock_filter macfilter[] = {
  BPF_STMT(BPF_LD|BPF_W|BPF_ABS, 2),
  BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0xaaaaaaaa, 0, 2),
  BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 0),
  BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0x0000aaaa, 2, 0),
  BPF_STMT(BPF_LD|BPF_B|BPF_ABS, 0),
  BPF_JUMP(BPF_JMP|BPF_JSET|BPF_K, 0x01, 0, 1),
  BPF_STMT(BPF_RET, 1514),
  BPF_STMT(BPF_RET, 0),
};
#define BX_LSF_ICNT 8    // number of lsf instructions in macfilter

#if 0
// template filter for all frames
static const struct sock_filter promiscfilter[] = {
  BPF_STMT(BPF_RET, 1514)
};
#endif

//
//  Define the class. This is private to this module
//
class bx_linux_pktmover_c : public eth_pktmover_c {
public:
  bx_linux_pktmover_c(const char *netif,
		     const char *macaddr,
		     eth_rx_handler_t rxh,
		     void *rxarg,
		     char *script);
  void sendpkt(void *buf, unsigned io_len);

private:
  unsigned char *linux_macaddr[6];
  int fd;
  int ifindex;
  static void rx_timer_handler(void *);
  void rx_timer(void);
  int rx_timer_index;
  struct sock_filter filter[BX_LSF_ICNT];
};

//
//  Define the static class that registers the derived pktmover class,
// and allocates one on request.
//
class bx_linux_locator_c : public eth_locator_c {
public:
  bx_linux_locator_c(void) : eth_locator_c("linux") {}
protected:
  eth_pktmover_c *allocate(const char *netif,
			   const char *macaddr,
			   eth_rx_handler_t rxh,
			   void *rxarg, char *script) {
    return (new bx_linux_pktmover_c(netif, macaddr, rxh, rxarg, script));
  }
} bx_linux_match;

//
// Define the methods for the bx_linux_pktmover derived class
//

// the constructor
//
bx_linux_pktmover_c::bx_linux_pktmover_c(const char *netif,
				       const char *macaddr,
				       eth_rx_handler_t rxh,
				       void *rxarg,
				       char *script)
{
  struct sockaddr_ll sll;
  struct packet_mreq mr;
  struct ifreq ifr;
  struct sock_fprog fp;

  memcpy(linux_macaddr, macaddr, 6);

  // Open packet socket
  //
  if ((this->fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) {
    if (errno == EACCES)
      BX_PANIC(("eth_linux: must be root or have CAP_NET_RAW capability to open socket"));
    else
      BX_PANIC(("eth_linux: could not open socket: %s", strerror(errno)));
    this->fd = -1;
    return;
  }

  // Translate interface name to index
  //
  memset(&ifr, 0, sizeof(ifr));
  strcpy(ifr.ifr_name, netif);
  if (ioctl(this->fd, SIOCGIFINDEX, &ifr) == -1) {
    BX_PANIC(("eth_linux: could not get index for interface '%s'\n", netif));
    close(fd);
    this->fd = -1;
    return;
  }
  this->ifindex = ifr.ifr_ifindex;

  // Bind to given interface
  //
  memset(&sll, 0, sizeof(sll));
  sll.sll_family = AF_PACKET;
  sll.sll_ifindex = this->ifindex;
  if (bind(fd, (struct sockaddr *)&sll, (socklen_t)sizeof(sll)) == -1) {
    BX_PANIC(("eth_linux: could not bind to interface '%s': %s\n", netif, strerror(errno)));
    close(fd);
    this->fd = -1;
    return;
  }

  // Put the device into promisc mode.
  //
  memset(&mr, 0, sizeof(mr));
  mr.mr_ifindex = this->ifindex;
  mr.mr_type = PACKET_MR_PROMISC;
  if (setsockopt(this->fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, (void *)&mr, (socklen_t)sizeof(mr)) == -1) {
    BX_PANIC(("eth_linux: could not enable promisc mode: %s\n", strerror(errno)));
    close(this->fd);
    this->fd = -1;
    return;
  }

  // Set up non-blocking i/o
  if (fcntl(this->fd, F_SETFL, O_NONBLOCK) == -1) {
    BX_PANIC(("eth_linux: could not set non-blocking i/o on socket"));
    close(this->fd);
    this->fd = -1;
    return;
  }

  // Install a filter
#ifdef notdef
  memcpy(&this->filter, promiscfilter, sizeof(promiscfilter));
  fp.len   = 1;
#endif
  memcpy(&this->filter, macfilter, sizeof(macfilter));
  this->filter[1].k = (macaddr[2] & 0xff) << 24 | (macaddr[3] & 0xff) << 16 |
    (macaddr[4] & 0xff) << 8  | (macaddr[5] & 0xff);
  this->filter[3].k = (macaddr[0] & 0xff) << 8 | (macaddr[1] & 0xff);
  fp.len = BX_LSF_ICNT;
  fp.filter = this->filter;
  BX_INFO(("eth_linux: fp.len=%d fp.filter=%x", fp.len, (unsigned) fp.filter));
  if (setsockopt(this->fd, SOL_SOCKET, SO_ATTACH_FILTER, &fp, sizeof(fp)) < 0) {
    BX_PANIC(("eth_linux: could not set socket filter: %s", strerror(errno)));
    close(this->fd);
    this->fd = -1;
    return;
  }

  // Start the rx poll
  this->rx_timer_index =
    bx_pc_system.register_timer(this, this->rx_timer_handler, BX_PACKET_POLL,
				1, 1, "eth_linux"); // continuous, active

  this->rxh   = rxh;
  this->rxarg = rxarg;
  BX_INFO(("eth_linux: enabled NE2K emulation on interface %s", netif));
}

// the output routine - called with pre-formatted ethernet frame.
void
bx_linux_pktmover_c::sendpkt(void *buf, unsigned io_len)
{
  int status;

  if (this->fd != -1) {
    status = write(this->fd, buf, io_len);
    if (status == -1)
      BX_INFO(("eth_linux: write failed: %s", strerror(errno)));
  }
}

// The receive poll process
void
bx_linux_pktmover_c::rx_timer_handler(void *this_ptr)
{
  bx_linux_pktmover_c *class_ptr = (bx_linux_pktmover_c *) this_ptr;

  class_ptr->rx_timer();
}

void
bx_linux_pktmover_c::rx_timer(void)
{
  int nbytes = 0;
  Bit8u rxbuf[BX_PACKET_BUFSIZE];
  struct sockaddr_ll sll;
  socklen_t fromlen;

  if (this->fd == -1)
    return;

  fromlen = sizeof(sll);
  nbytes = recvfrom(this->fd, rxbuf, sizeof(rxbuf), 0, (struct sockaddr *)&sll, &fromlen);

  if (nbytes == -1) {
    if (errno != EAGAIN)
      BX_INFO(("eth_linux: error receiving packet: %s\n", strerror(errno)));
    return;
  }

  // this should be done with LSF someday
  // filter out packets sourced by us
  if (memcmp(sll.sll_addr, this->linux_macaddr, 6) == 0)
    return;
  // let through broadcast, multicast, and our mac address
//  if ((memcmp(rxbuf, broadcast_macaddr, 6) == 0) || (memcmp(rxbuf, this->linux_macaddr, 6) == 0) || rxbuf[0] & 0x01) {
    BX_DEBUG(("eth_linux: got packet: %d bytes, dst=%x:%x:%x:%x:%x:%x, src=%x:%x:%x:%x:%x:%x\n", nbytes, rxbuf[0], rxbuf[1], rxbuf[2], rxbuf[3], rxbuf[4], rxbuf[5], rxbuf[6], rxbuf[7], rxbuf[8], rxbuf[9], rxbuf[10], rxbuf[11]));
    (*rxh)(rxarg, rxbuf, nbytes);
//  }
}
#endif /* if BX_NETWORKING && defined ETH_LINUX */
<commit_msg>- fixed compilation with x86_64 and gcc4 (SF patch #1211525 by scop)<commit_after>/////////////////////////////////////////////////////////////////////////
// $Id: eth_linux.cc,v 1.21 2005/06/05 07:24:43 vruppert Exp $
/////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2001  MandrakeSoft S.A.
//
//    MandrakeSoft S.A.
//    43, rue d'Aboukir
//    75002 Paris - France
//    http://www.linux-mandrake.com/
//    http://www.mandrakesoft.com/
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library 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
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

// Peter Grehan (grehan@iprg.nokia.com) coded all of this
// NE2000/ether stuff.

// eth_linux.cc - A Linux socket filter adaptation of the FreeBSD BPF driver
// <splite@purdue.edu> 21 June 2001
//
// Problems and limitations:
//   - packets cannot be sent from BOCHS to the host
//   - Linux kernel sometimes gets network watchdog timeouts under emulation
//   - author doesn't know C++
//
//   The config line in .bochsrc should look something like:
//
//  ne2k: ioaddr=0x280, irq=10, mac=00:a:b:c:1:2, ethmod=linux, ethdev=eth0
//

// Define BX_PLUGGABLE in files that can be compiled into plugins.  For
// platforms that require a special tag on exported symbols, BX_PLUGGABLE
// is used to know when we are exporting symbols and when we are importing.
#define BX_PLUGGABLE

#include "iodev.h"
#if BX_NETWORKING && defined (ETH_LINUX)

#include "eth.h"

#define LOG_THIS bx_devices.pluginNE2kDevice->

extern "C" {
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netpacket/packet.h>
#include <netinet/in.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <linux/types.h>
#include <linux/filter.h>
};

#define BX_PACKET_POLL  1000    // Poll for a frame every 1000 usecs

// template filter for a unicast mac address and all
// multicast/broadcast frames
static const struct sock_filter macfilter[] = {
  BPF_STMT(BPF_LD|BPF_W|BPF_ABS, 2),
  BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0xaaaaaaaa, 0, 2),
  BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 0),
  BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0x0000aaaa, 2, 0),
  BPF_STMT(BPF_LD|BPF_B|BPF_ABS, 0),
  BPF_JUMP(BPF_JMP|BPF_JSET|BPF_K, 0x01, 0, 1),
  BPF_STMT(BPF_RET, 1514),
  BPF_STMT(BPF_RET, 0),
};
#define BX_LSF_ICNT 8    // number of lsf instructions in macfilter

#if 0
// template filter for all frames
static const struct sock_filter promiscfilter[] = {
  BPF_STMT(BPF_RET, 1514)
};
#endif

//
//  Define the class. This is private to this module
//
class bx_linux_pktmover_c : public eth_pktmover_c {
public:
  bx_linux_pktmover_c(const char *netif,
		     const char *macaddr,
		     eth_rx_handler_t rxh,
		     void *rxarg,
		     char *script);
  void sendpkt(void *buf, unsigned io_len);

private:
  unsigned char *linux_macaddr[6];
  int fd;
  int ifindex;
  static void rx_timer_handler(void *);
  void rx_timer(void);
  int rx_timer_index;
  struct sock_filter filter[BX_LSF_ICNT];
};

//
//  Define the static class that registers the derived pktmover class,
// and allocates one on request.
//
class bx_linux_locator_c : public eth_locator_c {
public:
  bx_linux_locator_c(void) : eth_locator_c("linux") {}
protected:
  eth_pktmover_c *allocate(const char *netif,
			   const char *macaddr,
			   eth_rx_handler_t rxh,
			   void *rxarg, char *script) {
    return (new bx_linux_pktmover_c(netif, macaddr, rxh, rxarg, script));
  }
} bx_linux_match;

//
// Define the methods for the bx_linux_pktmover derived class
//

// the constructor
//
bx_linux_pktmover_c::bx_linux_pktmover_c(const char *netif,
				       const char *macaddr,
				       eth_rx_handler_t rxh,
				       void *rxarg,
				       char *script)
{
  struct sockaddr_ll sll;
  struct packet_mreq mr;
  struct ifreq ifr;
  struct sock_fprog fp;

  memcpy(linux_macaddr, macaddr, 6);

  // Open packet socket
  //
  if ((this->fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) {
    if (errno == EACCES)
      BX_PANIC(("eth_linux: must be root or have CAP_NET_RAW capability to open socket"));
    else
      BX_PANIC(("eth_linux: could not open socket: %s", strerror(errno)));
    this->fd = -1;
    return;
  }

  // Translate interface name to index
  //
  memset(&ifr, 0, sizeof(ifr));
  strcpy(ifr.ifr_name, netif);
  if (ioctl(this->fd, SIOCGIFINDEX, &ifr) == -1) {
    BX_PANIC(("eth_linux: could not get index for interface '%s'\n", netif));
    close(fd);
    this->fd = -1;
    return;
  }
  this->ifindex = ifr.ifr_ifindex;

  // Bind to given interface
  //
  memset(&sll, 0, sizeof(sll));
  sll.sll_family = AF_PACKET;
  sll.sll_ifindex = this->ifindex;
  if (bind(fd, (struct sockaddr *)&sll, (socklen_t)sizeof(sll)) == -1) {
    BX_PANIC(("eth_linux: could not bind to interface '%s': %s\n", netif, strerror(errno)));
    close(fd);
    this->fd = -1;
    return;
  }

  // Put the device into promisc mode.
  //
  memset(&mr, 0, sizeof(mr));
  mr.mr_ifindex = this->ifindex;
  mr.mr_type = PACKET_MR_PROMISC;
  if (setsockopt(this->fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, (void *)&mr, (socklen_t)sizeof(mr)) == -1) {
    BX_PANIC(("eth_linux: could not enable promisc mode: %s\n", strerror(errno)));
    close(this->fd);
    this->fd = -1;
    return;
  }

  // Set up non-blocking i/o
  if (fcntl(this->fd, F_SETFL, O_NONBLOCK) == -1) {
    BX_PANIC(("eth_linux: could not set non-blocking i/o on socket"));
    close(this->fd);
    this->fd = -1;
    return;
  }

  // Install a filter
#ifdef notdef
  memcpy(&this->filter, promiscfilter, sizeof(promiscfilter));
  fp.len   = 1;
#endif
  memcpy(&this->filter, macfilter, sizeof(macfilter));
  this->filter[1].k = (macaddr[2] & 0xff) << 24 | (macaddr[3] & 0xff) << 16 |
    (macaddr[4] & 0xff) << 8  | (macaddr[5] & 0xff);
  this->filter[3].k = (macaddr[0] & 0xff) << 8 | (macaddr[1] & 0xff);
  fp.len = BX_LSF_ICNT;
  fp.filter = this->filter;
  BX_INFO(("eth_linux: fp.len=%d fp.filter=%lx", fp.len, (unsigned long) fp.filter));
  if (setsockopt(this->fd, SOL_SOCKET, SO_ATTACH_FILTER, &fp, sizeof(fp)) < 0) {
    BX_PANIC(("eth_linux: could not set socket filter: %s", strerror(errno)));
    close(this->fd);
    this->fd = -1;
    return;
  }

  // Start the rx poll
  this->rx_timer_index =
    bx_pc_system.register_timer(this, this->rx_timer_handler, BX_PACKET_POLL,
				1, 1, "eth_linux"); // continuous, active

  this->rxh   = rxh;
  this->rxarg = rxarg;
  BX_INFO(("eth_linux: enabled NE2K emulation on interface %s", netif));
}

// the output routine - called with pre-formatted ethernet frame.
void
bx_linux_pktmover_c::sendpkt(void *buf, unsigned io_len)
{
  int status;

  if (this->fd != -1) {
    status = write(this->fd, buf, io_len);
    if (status == -1)
      BX_INFO(("eth_linux: write failed: %s", strerror(errno)));
  }
}

// The receive poll process
void
bx_linux_pktmover_c::rx_timer_handler(void *this_ptr)
{
  bx_linux_pktmover_c *class_ptr = (bx_linux_pktmover_c *) this_ptr;

  class_ptr->rx_timer();
}

void
bx_linux_pktmover_c::rx_timer(void)
{
  int nbytes = 0;
  Bit8u rxbuf[BX_PACKET_BUFSIZE];
  struct sockaddr_ll sll;
  socklen_t fromlen;

  if (this->fd == -1)
    return;

  fromlen = sizeof(sll);
  nbytes = recvfrom(this->fd, rxbuf, sizeof(rxbuf), 0, (struct sockaddr *)&sll, &fromlen);

  if (nbytes == -1) {
    if (errno != EAGAIN)
      BX_INFO(("eth_linux: error receiving packet: %s\n", strerror(errno)));
    return;
  }

  // this should be done with LSF someday
  // filter out packets sourced by us
  if (memcmp(sll.sll_addr, this->linux_macaddr, 6) == 0)
    return;
  // let through broadcast, multicast, and our mac address
//  if ((memcmp(rxbuf, broadcast_macaddr, 6) == 0) || (memcmp(rxbuf, this->linux_macaddr, 6) == 0) || rxbuf[0] & 0x01) {
    BX_DEBUG(("eth_linux: got packet: %d bytes, dst=%x:%x:%x:%x:%x:%x, src=%x:%x:%x:%x:%x:%x\n", nbytes, rxbuf[0], rxbuf[1], rxbuf[2], rxbuf[3], rxbuf[4], rxbuf[5], rxbuf[6], rxbuf[7], rxbuf[8], rxbuf[9], rxbuf[10], rxbuf[11]));
    (*rxh)(rxarg, rxbuf, nbytes);
//  }
}
#endif /* if BX_NETWORKING && defined ETH_LINUX */
<|endoftext|>


<commit_before>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>

//Mitk
#include <mitkDataNode.h>
#include <mitkNodePredicateNot.h>
#include <mitkNodePredicateProperty.h>
#include <mitkIRenderingManager.h>

// Qmitk
#include "UltrasoundSupport.h"
#include <QTimer>

// Qt
#include <QMessageBox>

// Ultrasound
#include "mitkUSDevice.h"
#include "QmitkUSAbstractCustomWidget.h"

#include <usModuleContext.h>
#include <usGetModuleContext.h>
#include "usServiceReference.h"
#include "internal/org_mitk_gui_qt_ultrasound_Activator.h"

const std::string UltrasoundSupport::VIEW_ID = "org.mitk.views.ultrasoundsupport";

void UltrasoundSupport::SetFocus()
{
}

void UltrasoundSupport::CreateQtPartControl( QWidget *parent )
{
  m_Timer = new QTimer(this);

  // create GUI widgets from the Qt Designer's .ui file
  m_Controls.setupUi( parent );

  connect( m_Controls.m_DeviceManagerWidget, SIGNAL(NewDeviceButtonClicked()), this, SLOT(OnClickedAddNewDevice()) ); // Change Widget Visibilities
  connect( m_Controls.m_DeviceManagerWidget, SIGNAL(NewDeviceButtonClicked()), this->m_Controls.m_NewVideoDeviceWidget, SLOT(CreateNewDevice()) ); // Init NewDeviceWidget
  connect( m_Controls.m_NewVideoDeviceWidget, SIGNAL(Finished()), this, SLOT(OnNewDeviceWidgetDone()) ); // After NewDeviceWidget finished editing
  connect( m_Controls.m_BtnView, SIGNAL(clicked()), this, SLOT(OnClickedViewDevice()) );
  connect( m_Controls.m_FrameRate, SIGNAL(valueChanged(int)), this, SLOT(OnChangedFramerateLimit(int)) );
  connect( m_Controls.m_FreezeButton, SIGNAL(clicked()), this, SLOT(OnClickedFreezeButton()) );
  connect( m_Timer, SIGNAL(timeout()), this, SLOT(DisplayImage()));

  // Initializations
  m_Controls.m_NewVideoDeviceWidget->setVisible(false);
  std::string filter = "(&(" + us::ServiceConstants::OBJECTCLASS() + "="
      + "org.mitk.services.UltrasoundDevice)("
      + mitk::USDevice::GetPropertyKeys().US_PROPKEY_ISACTIVE + "=true))";
  m_Controls.m_ActiveVideoDevices->Initialize<mitk::USDevice>(
        mitk::USDevice::GetPropertyKeys().US_PROPKEY_LABEL ,filter);

  m_Node = this->GetDataStorage()->GetNamedNode("US Image Stream");
  if (m_Node.IsNull())
  {
    // Create Node for US Stream
    m_Node = mitk::DataNode::New();
    m_Node->SetName("US Image Stream");
    this->GetDataStorage()->Add(m_Node);
  }

  m_Controls.tabWidget->setTabEnabled(1, false);
}

void UltrasoundSupport::OnClickedAddNewDevice()
{
  m_Controls.m_NewVideoDeviceWidget->setVisible(true);
  m_Controls.m_DeviceManagerWidget->setVisible(false);
  m_Controls.m_Headline->setText("Add New Video Device:");
  m_Controls.m_WidgetActiveDevices->setVisible(false);
}

void UltrasoundSupport::DisplayImage()
{
  m_Device->Modified();
  m_Device->Update();

  mitk::Image::Pointer curOutput = m_Device->GetOutput();
  if (! m_ImageAlreadySetToNode && curOutput.IsNotNull() && curOutput->IsInitialized())
  {
    m_Node->SetData(curOutput);
    m_ImageAlreadySetToNode = true;
  }

  if ( curOutput.GetPointer() != m_Node->GetData() )
  {
    MITK_INFO << "Data Node of the ultrasound image stream was changed by another plugin. Stop viewing.";
    this->StopViewing();
    return;
  }

  this->RequestRenderWindowUpdate();

  if ( curOutput->GetDimension() > 1
    && (curOutput->GetDimension(0) != m_CurrentImageWidth
    || curOutput->GetDimension(1) != m_CurrentImageHeight) )
  {
    // make a reinit on the ultrasound image
    mitk::IRenderWindowPart* renderWindow = this->GetRenderWindowPart();
    if ( renderWindow != NULL && curOutput->GetTimeGeometry()->IsValid() )
    {
      renderWindow->GetRenderingManager()->InitializeViews(
        curOutput->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true );
      renderWindow->GetRenderingManager()->RequestUpdateAll();
    }

    m_CurrentImageWidth = curOutput->GetDimension(0);
    m_CurrentImageHeight = curOutput->GetDimension(1);
  }

  m_FrameCounter ++;
  if (m_FrameCounter == 10)
  {
    int nMilliseconds = m_Clock.restart();
    int fps = 10000.0f / (nMilliseconds );
    m_Controls.m_FramerateLabel->setText("Current Framerate: "+ QString::number(fps) +" FPS");
    m_FrameCounter = 0;
  }
}

void UltrasoundSupport::OnClickedViewDevice()
{
  m_FrameCounter = 0;
  // We use the activity state of the timer to determine whether we are currently viewing images
  if ( ! m_Timer->isActive() ) // Activate Imaging
  {
    this->StartViewing();
  }
  else //deactivate imaging
  {
    this->StopViewing();
  }
}

void UltrasoundSupport::OnChangedFramerateLimit(int value)
{
  m_Timer->setInterval(1000 / value);
}

void UltrasoundSupport::OnClickedFreezeButton()
{
  if ( m_Device->GetIsFreezed() )
  {
    m_Device->SetIsFreezed(false);
    m_Controls.m_FreezeButton->setText("Freeze");
  }
  else
  {
    m_Device->SetIsFreezed(true);
    m_Controls.m_FreezeButton->setText("Start Viewing Again");
  }
}

void UltrasoundSupport::OnNewDeviceWidgetDone()
{
  m_Controls.m_NewVideoDeviceWidget->setVisible(false);
  m_Controls.m_DeviceManagerWidget->setVisible(true);
  m_Controls.m_Headline->setText("Ultrasound Devices:");
  m_Controls.m_WidgetActiveDevices->setVisible(true);
}

void UltrasoundSupport::StartViewing()
{
  m_ImageAlreadySetToNode = false;

  m_Controls.tabWidget->setTabEnabled(1, true);
  m_Controls.tabWidget->setCurrentIndex(1);

  //get device & set data node
  m_Device = m_Controls.m_ActiveVideoDevices->GetSelectedService<mitk::USDevice>();
  if (m_Device.IsNull())
  {
    m_Timer->stop();
    return;
  }

  //start timer
  int interval = (1000 / m_Controls.m_FrameRate->value());
  m_Timer->setInterval(interval);
  m_Timer->start();

  //change UI elements
  m_Controls.m_BtnView->setText("Stop Viewing");

  this->CreateControlWidgets();
}

void UltrasoundSupport::StopViewing()
{
  m_Controls.tabWidget->setTabEnabled(1, false);

  this->RemoveControlWidgets();

  //stop timer & release data
  m_Timer->stop();
  m_Node->ReleaseData();
  this->RequestRenderWindowUpdate();

  //change UI elements
  m_Controls.m_BtnView->setText("Start Viewing");
}

void UltrasoundSupport::CreateControlWidgets()
{
  m_ControlProbesWidget = new QmitkUSControlsProbesWidget(m_Device->GetControlInterfaceProbes(), m_Controls.m_ToolBoxControlWidgets);
  m_Controls.probesWidgetContainer->addWidget(m_ControlProbesWidget);

  // create b mode widget for current device
  m_ControlBModeWidget = new QmitkUSControlsBModeWidget(m_Device->GetControlInterfaceBMode(), m_Controls.m_ToolBoxControlWidgets);
  m_Controls.m_ToolBoxControlWidgets->addItem(m_ControlBModeWidget, "B Mode Controls");
  if ( ! m_Device->GetControlInterfaceBMode() )
  {
    m_Controls.m_ToolBoxControlWidgets->setItemEnabled(m_Controls.m_ToolBoxControlWidgets->count()-1, false);
  }

  // create doppler widget for current device
  m_ControlDopplerWidget = new QmitkUSControlsDopplerWidget(m_Device->GetControlInterfaceDoppler(), m_Controls.m_ToolBoxControlWidgets);
  m_Controls.m_ToolBoxControlWidgets->addItem(m_ControlDopplerWidget, "Doppler Controls");
  if ( ! m_Device->GetControlInterfaceDoppler() )
  {
    m_Controls.m_ToolBoxControlWidgets->setItemEnabled(m_Controls.m_ToolBoxControlWidgets->count()-1, false);
  }

  ctkPluginContext* pluginContext = mitk::PluginActivator::GetContext();
  if ( pluginContext )
  {
    std::string filter = "(ork.mitk.services.UltrasoundCustomWidget.deviceClass=" + m_Device->GetDeviceClass() + ")";

    QString interfaceName ( us_service_interface_iid<QmitkUSAbstractCustomWidget>() );
    m_CustomWidgetServiceReference = pluginContext->getServiceReferences(interfaceName, QString::fromStdString(filter));

    if (m_CustomWidgetServiceReference.size() > 0)
    {
      m_ControlCustomWidget = pluginContext->getService<QmitkUSAbstractCustomWidget>
        (m_CustomWidgetServiceReference.at(0))->CloneForQt(m_Controls.tab2);
      m_ControlCustomWidget->SetDevice(m_Device);
      m_Controls.m_ToolBoxControlWidgets->addItem(m_ControlCustomWidget, "Custom Controls");
    }
    else
    {
      m_Controls.m_ToolBoxControlWidgets->addItem(new QWidget(m_Controls.m_ToolBoxControlWidgets), "Custom Controls");
      m_Controls.m_ToolBoxControlWidgets->setItemEnabled(m_Controls.m_ToolBoxControlWidgets->count()-1, false);
    }
  }

  // select first enabled control widget
  for ( int n = 0; n < m_Controls.m_ToolBoxControlWidgets->count(); ++n)
  {
    if ( m_Controls.m_ToolBoxControlWidgets->isItemEnabled(n) )
    {
      m_Controls.m_ToolBoxControlWidgets->setCurrentIndex(n);
      break;
    }
  }
}

void UltrasoundSupport::RemoveControlWidgets()
{
  // remove all control widgets from the tool box widget
  while (m_Controls.m_ToolBoxControlWidgets->count() > 0)
  {
    m_Controls.m_ToolBoxControlWidgets->removeItem(0);
  }

  // remove probes widget (which is not part of the tool box widget)
  m_Controls.probesWidgetContainer->removeWidget(m_ControlProbesWidget);
  delete m_ControlProbesWidget;
  m_ControlProbesWidget = 0;

  delete m_ControlBModeWidget;
  m_ControlBModeWidget = 0;

  delete m_ControlDopplerWidget;
  m_ControlDopplerWidget = 0;

  // delete custom widget if it is present
  if ( m_ControlCustomWidget )
  {
    ctkPluginContext* pluginContext = mitk::PluginActivator::GetContext();
    delete m_ControlCustomWidget; m_ControlCustomWidget = 0;

    if ( m_CustomWidgetServiceReference.size() > 0 )
    {
      pluginContext->ungetService(m_CustomWidgetServiceReference.at(0));
    }
  }
}

void UltrasoundSupport::OnDeciveServiceEvent(const ctkServiceEvent event)
{
  if ( m_Device.IsNull() || event.getType() != us::ServiceEvent::MODIFIED ) { return; }

  ctkServiceReference service = event.getServiceReference();

  if ( m_Device->GetDeviceManufacturer() != service.getProperty(mitk::USImageMetadata::PROP_DEV_MANUFACTURER).toString().toStdString()
    && m_Device->GetDeviceModel() != service.getProperty(mitk::USImageMetadata::PROP_DEV_MODEL).toString().toStdString() )
  {
    return;
  }

  if ( ! m_Device->GetIsActive() && m_Timer->isActive() )
  {
    this->StopViewing();
  }
}

UltrasoundSupport::UltrasoundSupport()
: m_ControlCustomWidget(0), m_ControlBModeWidget(0),
  m_ControlProbesWidget(0), m_ImageAlreadySetToNode(false),
  m_CurrentImageWidth(0), m_CurrentImageHeight(0)
{
  ctkPluginContext* pluginContext = mitk::PluginActivator::GetContext();

  if ( pluginContext )
  {
    // to be notified about service event of an USDevice
    pluginContext->connectServiceListener(this, "OnDeciveServiceEvent",
      QString::fromStdString("(" + us::ServiceConstants::OBJECTCLASS() + "=" + us_service_interface_iid<mitk::USDevice>() + ")"));
  }
}

UltrasoundSupport::~UltrasoundSupport()
{
}
<commit_msg>Removed usage of USImageMetadata from the UltrasoundSupport plugin.<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>

//Mitk
#include <mitkDataNode.h>
#include <mitkNodePredicateNot.h>
#include <mitkNodePredicateProperty.h>
#include <mitkIRenderingManager.h>

// Qmitk
#include "UltrasoundSupport.h"
#include <QTimer>

// Qt
#include <QMessageBox>

// Ultrasound
#include "mitkUSDevice.h"
#include "QmitkUSAbstractCustomWidget.h"

#include <usModuleContext.h>
#include <usGetModuleContext.h>
#include "usServiceReference.h"
#include "internal/org_mitk_gui_qt_ultrasound_Activator.h"

const std::string UltrasoundSupport::VIEW_ID = "org.mitk.views.ultrasoundsupport";

void UltrasoundSupport::SetFocus()
{
}

void UltrasoundSupport::CreateQtPartControl( QWidget *parent )
{
  m_Timer = new QTimer(this);

  // create GUI widgets from the Qt Designer's .ui file
  m_Controls.setupUi( parent );

  connect( m_Controls.m_DeviceManagerWidget, SIGNAL(NewDeviceButtonClicked()), this, SLOT(OnClickedAddNewDevice()) ); // Change Widget Visibilities
  connect( m_Controls.m_DeviceManagerWidget, SIGNAL(NewDeviceButtonClicked()), this->m_Controls.m_NewVideoDeviceWidget, SLOT(CreateNewDevice()) ); // Init NewDeviceWidget
  connect( m_Controls.m_NewVideoDeviceWidget, SIGNAL(Finished()), this, SLOT(OnNewDeviceWidgetDone()) ); // After NewDeviceWidget finished editing
  connect( m_Controls.m_BtnView, SIGNAL(clicked()), this, SLOT(OnClickedViewDevice()) );
  connect( m_Controls.m_FrameRate, SIGNAL(valueChanged(int)), this, SLOT(OnChangedFramerateLimit(int)) );
  connect( m_Controls.m_FreezeButton, SIGNAL(clicked()), this, SLOT(OnClickedFreezeButton()) );
  connect( m_Timer, SIGNAL(timeout()), this, SLOT(DisplayImage()));

  // Initializations
  m_Controls.m_NewVideoDeviceWidget->setVisible(false);
  std::string filter = "(&(" + us::ServiceConstants::OBJECTCLASS() + "="
      + "org.mitk.services.UltrasoundDevice)("
      + mitk::USDevice::GetPropertyKeys().US_PROPKEY_ISACTIVE + "=true))";
  m_Controls.m_ActiveVideoDevices->Initialize<mitk::USDevice>(
        mitk::USDevice::GetPropertyKeys().US_PROPKEY_LABEL ,filter);

  m_Node = this->GetDataStorage()->GetNamedNode("US Image Stream");
  if (m_Node.IsNull())
  {
    // Create Node for US Stream
    m_Node = mitk::DataNode::New();
    m_Node->SetName("US Image Stream");
    this->GetDataStorage()->Add(m_Node);
  }

  m_Controls.tabWidget->setTabEnabled(1, false);
}

void UltrasoundSupport::OnClickedAddNewDevice()
{
  m_Controls.m_NewVideoDeviceWidget->setVisible(true);
  m_Controls.m_DeviceManagerWidget->setVisible(false);
  m_Controls.m_Headline->setText("Add New Video Device:");
  m_Controls.m_WidgetActiveDevices->setVisible(false);
}

void UltrasoundSupport::DisplayImage()
{
  m_Device->Modified();
  m_Device->Update();

  mitk::Image::Pointer curOutput = m_Device->GetOutput();
  if (! m_ImageAlreadySetToNode && curOutput.IsNotNull() && curOutput->IsInitialized())
  {
    m_Node->SetData(curOutput);
    m_ImageAlreadySetToNode = true;
  }

  if ( curOutput.GetPointer() != m_Node->GetData() )
  {
    MITK_INFO << "Data Node of the ultrasound image stream was changed by another plugin. Stop viewing.";
    this->StopViewing();
    return;
  }

  this->RequestRenderWindowUpdate();

  if ( curOutput->GetDimension() > 1
    && (curOutput->GetDimension(0) != m_CurrentImageWidth
    || curOutput->GetDimension(1) != m_CurrentImageHeight) )
  {
    // make a reinit on the ultrasound image
    mitk::IRenderWindowPart* renderWindow = this->GetRenderWindowPart();
    if ( renderWindow != NULL && curOutput->GetTimeGeometry()->IsValid() )
    {
      renderWindow->GetRenderingManager()->InitializeViews(
        curOutput->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true );
      renderWindow->GetRenderingManager()->RequestUpdateAll();
    }

    m_CurrentImageWidth = curOutput->GetDimension(0);
    m_CurrentImageHeight = curOutput->GetDimension(1);
  }

  m_FrameCounter ++;
  if (m_FrameCounter == 10)
  {
    int nMilliseconds = m_Clock.restart();
    int fps = 10000.0f / (nMilliseconds );
    m_Controls.m_FramerateLabel->setText("Current Framerate: "+ QString::number(fps) +" FPS");
    m_FrameCounter = 0;
  }
}

void UltrasoundSupport::OnClickedViewDevice()
{
  m_FrameCounter = 0;
  // We use the activity state of the timer to determine whether we are currently viewing images
  if ( ! m_Timer->isActive() ) // Activate Imaging
  {
    this->StartViewing();
  }
  else //deactivate imaging
  {
    this->StopViewing();
  }
}

void UltrasoundSupport::OnChangedFramerateLimit(int value)
{
  m_Timer->setInterval(1000 / value);
}

void UltrasoundSupport::OnClickedFreezeButton()
{
  if ( m_Device->GetIsFreezed() )
  {
    m_Device->SetIsFreezed(false);
    m_Controls.m_FreezeButton->setText("Freeze");
  }
  else
  {
    m_Device->SetIsFreezed(true);
    m_Controls.m_FreezeButton->setText("Start Viewing Again");
  }
}

void UltrasoundSupport::OnNewDeviceWidgetDone()
{
  m_Controls.m_NewVideoDeviceWidget->setVisible(false);
  m_Controls.m_DeviceManagerWidget->setVisible(true);
  m_Controls.m_Headline->setText("Ultrasound Devices:");
  m_Controls.m_WidgetActiveDevices->setVisible(true);
}

void UltrasoundSupport::StartViewing()
{
  m_ImageAlreadySetToNode = false;

  m_Controls.tabWidget->setTabEnabled(1, true);
  m_Controls.tabWidget->setCurrentIndex(1);

  //get device & set data node
  m_Device = m_Controls.m_ActiveVideoDevices->GetSelectedService<mitk::USDevice>();
  if (m_Device.IsNull())
  {
    m_Timer->stop();
    return;
  }

  //start timer
  int interval = (1000 / m_Controls.m_FrameRate->value());
  m_Timer->setInterval(interval);
  m_Timer->start();

  //change UI elements
  m_Controls.m_BtnView->setText("Stop Viewing");

  this->CreateControlWidgets();
}

void UltrasoundSupport::StopViewing()
{
  m_Controls.tabWidget->setTabEnabled(1, false);

  this->RemoveControlWidgets();

  //stop timer & release data
  m_Timer->stop();
  m_Node->ReleaseData();
  this->RequestRenderWindowUpdate();

  //change UI elements
  m_Controls.m_BtnView->setText("Start Viewing");
}

void UltrasoundSupport::CreateControlWidgets()
{
  m_ControlProbesWidget = new QmitkUSControlsProbesWidget(m_Device->GetControlInterfaceProbes(), m_Controls.m_ToolBoxControlWidgets);
  m_Controls.probesWidgetContainer->addWidget(m_ControlProbesWidget);

  // create b mode widget for current device
  m_ControlBModeWidget = new QmitkUSControlsBModeWidget(m_Device->GetControlInterfaceBMode(), m_Controls.m_ToolBoxControlWidgets);
  m_Controls.m_ToolBoxControlWidgets->addItem(m_ControlBModeWidget, "B Mode Controls");
  if ( ! m_Device->GetControlInterfaceBMode() )
  {
    m_Controls.m_ToolBoxControlWidgets->setItemEnabled(m_Controls.m_ToolBoxControlWidgets->count()-1, false);
  }

  // create doppler widget for current device
  m_ControlDopplerWidget = new QmitkUSControlsDopplerWidget(m_Device->GetControlInterfaceDoppler(), m_Controls.m_ToolBoxControlWidgets);
  m_Controls.m_ToolBoxControlWidgets->addItem(m_ControlDopplerWidget, "Doppler Controls");
  if ( ! m_Device->GetControlInterfaceDoppler() )
  {
    m_Controls.m_ToolBoxControlWidgets->setItemEnabled(m_Controls.m_ToolBoxControlWidgets->count()-1, false);
  }

  ctkPluginContext* pluginContext = mitk::PluginActivator::GetContext();
  if ( pluginContext )
  {
    std::string filter = "(ork.mitk.services.UltrasoundCustomWidget.deviceClass=" + m_Device->GetDeviceClass() + ")";

    QString interfaceName ( us_service_interface_iid<QmitkUSAbstractCustomWidget>() );
    m_CustomWidgetServiceReference = pluginContext->getServiceReferences(interfaceName, QString::fromStdString(filter));

    if (m_CustomWidgetServiceReference.size() > 0)
    {
      m_ControlCustomWidget = pluginContext->getService<QmitkUSAbstractCustomWidget>
        (m_CustomWidgetServiceReference.at(0))->CloneForQt(m_Controls.tab2);
      m_ControlCustomWidget->SetDevice(m_Device);
      m_Controls.m_ToolBoxControlWidgets->addItem(m_ControlCustomWidget, "Custom Controls");
    }
    else
    {
      m_Controls.m_ToolBoxControlWidgets->addItem(new QWidget(m_Controls.m_ToolBoxControlWidgets), "Custom Controls");
      m_Controls.m_ToolBoxControlWidgets->setItemEnabled(m_Controls.m_ToolBoxControlWidgets->count()-1, false);
    }
  }

  // select first enabled control widget
  for ( int n = 0; n < m_Controls.m_ToolBoxControlWidgets->count(); ++n)
  {
    if ( m_Controls.m_ToolBoxControlWidgets->isItemEnabled(n) )
    {
      m_Controls.m_ToolBoxControlWidgets->setCurrentIndex(n);
      break;
    }
  }
}

void UltrasoundSupport::RemoveControlWidgets()
{
  // remove all control widgets from the tool box widget
  while (m_Controls.m_ToolBoxControlWidgets->count() > 0)
  {
    m_Controls.m_ToolBoxControlWidgets->removeItem(0);
  }

  // remove probes widget (which is not part of the tool box widget)
  m_Controls.probesWidgetContainer->removeWidget(m_ControlProbesWidget);
  delete m_ControlProbesWidget;
  m_ControlProbesWidget = 0;

  delete m_ControlBModeWidget;
  m_ControlBModeWidget = 0;

  delete m_ControlDopplerWidget;
  m_ControlDopplerWidget = 0;

  // delete custom widget if it is present
  if ( m_ControlCustomWidget )
  {
    ctkPluginContext* pluginContext = mitk::PluginActivator::GetContext();
    delete m_ControlCustomWidget; m_ControlCustomWidget = 0;

    if ( m_CustomWidgetServiceReference.size() > 0 )
    {
      pluginContext->ungetService(m_CustomWidgetServiceReference.at(0));
    }
  }
}

void UltrasoundSupport::OnDeciveServiceEvent(const ctkServiceEvent event)
{
  if ( m_Device.IsNull() || event.getType() != us::ServiceEvent::MODIFIED ) { return; }

  ctkServiceReference service = event.getServiceReference();

  if ( m_Device->GetManufacturer() != service.getProperty(QString::fromStdString(mitk::USDevice::GetPropertyKeys().US_PROPKEY_MANUFACTURER)).toString().toStdString()
    && m_Device->GetName() != service.getProperty(QString::fromStdString(mitk::USDevice::GetPropertyKeys().US_PROPKEY_NAME)).toString().toStdString() )
  {
    return;
  }

  if ( ! m_Device->GetIsActive() && m_Timer->isActive() )
  {
    this->StopViewing();
  }
}

UltrasoundSupport::UltrasoundSupport()
: m_ControlCustomWidget(0), m_ControlBModeWidget(0),
  m_ControlProbesWidget(0), m_ImageAlreadySetToNode(false),
  m_CurrentImageWidth(0), m_CurrentImageHeight(0)
{
  ctkPluginContext* pluginContext = mitk::PluginActivator::GetContext();

  if ( pluginContext )
  {
    // to be notified about service event of an USDevice
    pluginContext->connectServiceListener(this, "OnDeciveServiceEvent",
      QString::fromStdString("(" + us::ServiceConstants::OBJECTCLASS() + "=" + us_service_interface_iid<mitk::USDevice>() + ")"));
  }
}

UltrasoundSupport::~UltrasoundSupport()
{
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_framework.hxx"

//________________________________
//  my own includes
#include <jobs/jobexecutor.hxx>
#include <jobs/job.hxx>
#include <jobs/joburl.hxx>

#include <classes/converter.hxx>
#include <threadhelp/transactionguard.hxx>
#include <threadhelp/readguard.hxx>
#include <threadhelp/writeguard.hxx>
#include <general.h>
#include <services.h>

#include "helper/mischelper.hxx"

//________________________________
//  interface includes
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/container/XContainer.hpp>

//________________________________
//  includes of other projects
#include <unotools/configpathes.hxx>
#include <rtl/ustrbuf.hxx>
#include <vcl/svapp.hxx>

#include <rtl/logfile.hxx>

//________________________________
//  namespace

namespace framework{

//________________________________
//  non exported const

//________________________________
//  non exported definitions

//________________________________
//  declarations

DEFINE_XINTERFACE_6( JobExecutor                                                               ,
                     OWeakObject                                                               ,
                     DIRECT_INTERFACE(css::lang::XTypeProvider                                ),
                     DIRECT_INTERFACE(css::lang::XServiceInfo                                 ),
                     DIRECT_INTERFACE(css::task::XJobExecutor                                 ),
                     DIRECT_INTERFACE(css::container::XContainerListener                      ),
                     DIRECT_INTERFACE(css::document::XEventListener                           ),
                     DERIVED_INTERFACE(css::lang::XEventListener,css::document::XEventListener)
                   )

DEFINE_XTYPEPROVIDER_6( JobExecutor                       ,
                        css::lang::XTypeProvider          ,
                        css::lang::XServiceInfo           ,
                        css::task::XJobExecutor           ,
                        css::container::XContainerListener,
                        css::document::XEventListener     ,
                        css::lang::XEventListener
                      )

DEFINE_XSERVICEINFO_ONEINSTANCESERVICE( JobExecutor                   ,
                                        ::cppu::OWeakObject           ,
                                        SERVICENAME_JOBEXECUTOR       ,
                                        IMPLEMENTATIONNAME_JOBEXECUTOR
                                      )

DEFINE_INIT_SERVICE( JobExecutor,
                     {
                         m_xModuleManager = css::uno::Reference< css::frame::XModuleManager >(
                             m_xSMGR->createInstance(
                                 SERVICENAME_MODULEMANAGER ),
                             css::uno::UNO_QUERY_THROW );

                         /*Attention
                             I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
                             to create a new instance of this class by our own supported service factory.
                             see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
                         */
                        // read the list of all currently registered events inside configuration.
                        // e.g. "/org.openoffice.Office.Jobs/Events/<event name>"
                        // We need it later to check if an incoming event request can be executed successfully
                        // or must be rejected. It's an optimization! Of course we must implement updating of this
                        // list too ... Be listener at the configuration.

                        m_aConfig.open(ConfigAccess::E_READONLY);
                        if (m_aConfig.getMode() == ConfigAccess::E_READONLY)
                        {
                            css::uno::Reference< css::container::XNameAccess > xRegistry(m_aConfig.cfg(), css::uno::UNO_QUERY);
                            if (xRegistry.is())
                                m_lEvents = Converter::convert_seqOUString2OUStringList(xRegistry->getElementNames());

                            css::uno::Reference< css::container::XContainer > xNotifier(m_aConfig.cfg(), css::uno::UNO_QUERY);
                            if (xNotifier.is())
                            {
                                m_xConfigListener = new WeakContainerListener(this);
                                xNotifier->addContainerListener(m_xConfigListener);
                            }

                            // don't close cfg here!
                            // It will be done inside disposing ...
                        }
                     }
                   )

//________________________________

/**
    @short      standard ctor
    @descr      It initialize this new instance.

    @param      xSMGR
                    reference to the uno service manager
 */
JobExecutor::JobExecutor( /*IN*/ const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR )
    : ThreadHelpBase      (&Application::GetSolarMutex()                                   )
    , ::cppu::OWeakObject (                                                                )
    , m_xSMGR             (xSMGR                                                           )
    , m_xModuleManager    (                                                                )
    , m_aConfig           (xSMGR, ::rtl::OUString::createFromAscii(JobData::EVENTCFG_ROOT) )
{
    // Don't do any reference related code here! Do it inside special
    // impl_ method() ... see DEFINE_INIT_SERVICE() macro for further informations.
}

JobExecutor::~JobExecutor()
{
    css::uno::Reference< css::container::XContainer > xNotifier(m_aConfig.cfg(), css::uno::UNO_QUERY);
    if (xNotifier.is())
        xNotifier->removeContainerListener(m_xConfigListener);
    LOG_ASSERT(m_aConfig.getMode() == ConfigAccess::E_CLOSED, "JobExecutor::~JobExecutor()\nConfiguration don't send dispoing() message!\n")
}

//________________________________

/**
    @short  implementation of XJobExecutor interface
    @descr  We use the given event to locate any registered job inside our configuration
            and execute it. Further we control the lifetime of it and supress
            shutdown of the office till all jobs was finished.

    @param  sEvent
                is used to locate registered jobs
 */
void SAL_CALL JobExecutor::trigger( const ::rtl::OUString& sEvent ) throw(css::uno::RuntimeException)
{
    RTL_LOGFILE_CONTEXT(aLog, "fwk (as96863) JobExecutor::trigger()");

    /* SAFE { */
    ReadGuard aReadLock(m_aLock);

    // Optimization!
    // Check if the given event name exist inside configuration and reject wrong requests.
    // This optimization supress using of the cfg api for getting event and job descriptions ...
    if (m_lEvents.find(sEvent) == m_lEvents.end())
        return;

    // get list of all enabled jobs
    // The called static helper methods read it from the configuration and
    // filter disabled jobs using it's time stamp values.
    css::uno::Sequence< ::rtl::OUString > lJobs = JobData::getEnabledJobsForEvent(m_xSMGR, sEvent);

    aReadLock.unlock();
    /* } SAFE */

    // step over all enabled jobs and execute it
    sal_Int32 c = lJobs.getLength();
    for (sal_Int32 j=0; j<c; ++j)
    {
        /* SAFE { */
        aReadLock.lock();

        JobData aCfg(m_xSMGR);
        aCfg.setEvent(sEvent, lJobs[j]);
        aCfg.setEnvironment(JobData::E_EXECUTION);

        /*Attention!
            Jobs implements interfaces and dies by ref count!
            And freeing of such uno object is done by uno itself.
            So we have to use dynamic memory everytimes.
         */
        Job* pJob = new Job(m_xSMGR, css::uno::Reference< css::frame::XFrame >());
        css::uno::Reference< css::uno::XInterface > xJob(static_cast< ::cppu::OWeakObject* >(pJob), css::uno::UNO_QUERY);
        pJob->setJobData(aCfg);

        aReadLock.unlock();
        /* } SAFE */

        pJob->execute(css::uno::Sequence< css::beans::NamedValue >());
    }
}

//________________________________

void SAL_CALL JobExecutor::notifyEvent( const css::document::EventObject& aEvent ) throw(css::uno::RuntimeException)
{
    static ::rtl::OUString EVENT_ON_NEW             = DECLARE_ASCII("OnNew"             ); // Doc UI  event
    static ::rtl::OUString EVENT_ON_LOAD            = DECLARE_ASCII("OnLoad"            ); // Doc UI  event
    static ::rtl::OUString EVENT_ON_CREATE          = DECLARE_ASCII("OnCreate"          ); // Doc API event
    static ::rtl::OUString EVENT_ON_LOAD_FINISHED   = DECLARE_ASCII("OnLoadFinished"    ); // Doc API event
    static ::rtl::OUString EVENT_ON_DOCUMENT_OPENED = DECLARE_ASCII("onDocumentOpened"  ); // Job UI  event : OnNew    or OnLoad
    static ::rtl::OUString EVENT_ON_DOCUMENT_ADDED  = DECLARE_ASCII("onDocumentAdded"   ); // Job API event : OnCreate or OnLoadFinished

    /* SAFE { */
    ReadGuard aReadLock(m_aLock);

    ::comphelper::SequenceAsVector< JobData::TJob2DocEventBinding > lJobs;

    // Optimization!
    // Check if the given event name exist inside configuration and reject wrong requests.
    // This optimization supress using of the cfg api for getting event and job descriptions.
    // see using of m_lEvents.find() below ...

    // retrieve event context from event source
    rtl::OUString aModuleIdentifier;
    try
    {
        aModuleIdentifier = m_xModuleManager->identify( aEvent.Source );
    }
    catch( css::uno::Exception& )
    {}

    // Special feature: If the events "OnNew" or "OnLoad" occures - we generate our own event "onDocumentOpened".
    if (
        (aEvent.EventName.equals(EVENT_ON_NEW )) ||
        (aEvent.EventName.equals(EVENT_ON_LOAD))
       )
    {
        if (m_lEvents.find(EVENT_ON_DOCUMENT_OPENED) != m_lEvents.end())
            JobData::appendEnabledJobsForEvent(m_xSMGR, EVENT_ON_DOCUMENT_OPENED, lJobs);
    }

    // Special feature: If the events "OnCreate" or "OnLoadFinished" occures - we generate our own event "onDocumentAdded".
    if (
        (aEvent.EventName.equals(EVENT_ON_CREATE       )) ||
        (aEvent.EventName.equals(EVENT_ON_LOAD_FINISHED))
       )
    {
        if (m_lEvents.find(EVENT_ON_DOCUMENT_ADDED) != m_lEvents.end())
            JobData::appendEnabledJobsForEvent(m_xSMGR, EVENT_ON_DOCUMENT_ADDED, lJobs);
    }

    // Add all jobs for "real" notified event too .-)
    if (m_lEvents.find(aEvent.EventName) != m_lEvents.end())
        JobData::appendEnabledJobsForEvent(m_xSMGR, aEvent.EventName, lJobs);

    aReadLock.unlock();
    /* } SAFE */

    // step over all enabled jobs and execute it
    ::comphelper::SequenceAsVector< JobData::TJob2DocEventBinding >::const_iterator pIt;
    for (  pIt  = lJobs.begin();
           pIt != lJobs.end()  ;
         ++pIt                 )
    {
        /* SAFE { */
        aReadLock.lock();

        const JobData::TJob2DocEventBinding& rBinding = *pIt;

        JobData aCfg(m_xSMGR);
        aCfg.setEvent(rBinding.m_sDocEvent, rBinding.m_sJobName);
        aCfg.setEnvironment(JobData::E_DOCUMENTEVENT);

        if (!aCfg.hasCorrectContext(aModuleIdentifier))
            continue;

        /*Attention!
            Jobs implements interfaces and dies by ref count!
            And freeing of such uno object is done by uno itself.
            So we have to use dynamic memory everytimes.
         */
        css::uno::Reference< css::frame::XModel > xModel(aEvent.Source, css::uno::UNO_QUERY);
        Job* pJob = new Job(m_xSMGR, xModel);
        css::uno::Reference< css::uno::XInterface > xJob(static_cast< ::cppu::OWeakObject* >(pJob), css::uno::UNO_QUERY);
        pJob->setJobData(aCfg);

        aReadLock.unlock();
        /* } SAFE */

        pJob->execute(css::uno::Sequence< css::beans::NamedValue >());
    }
}

//________________________________

void SAL_CALL JobExecutor::elementInserted( const css::container::ContainerEvent& aEvent ) throw(css::uno::RuntimeException)
{
    ::rtl::OUString sValue;
    if (aEvent.Accessor >>= sValue)
    {
        ::rtl::OUString sEvent = ::utl::extractFirstFromConfigurationPath(sValue);
        if (sEvent.getLength() > 0)
        {
            OUStringList::iterator pEvent = m_lEvents.find(sEvent);
            if (pEvent == m_lEvents.end())
                m_lEvents.push_back(sEvent);
        }
    }
}

void SAL_CALL JobExecutor::elementRemoved ( const css::container::ContainerEvent& aEvent ) throw(css::uno::RuntimeException)
{
    ::rtl::OUString sValue;
    if (aEvent.Accessor >>= sValue)
    {
        ::rtl::OUString sEvent = ::utl::extractFirstFromConfigurationPath(sValue);
        if (sEvent.getLength() > 0)
        {
            OUStringList::iterator pEvent = m_lEvents.find(sEvent);
            if (pEvent != m_lEvents.end())
                m_lEvents.erase(pEvent);
        }
    }
}

void SAL_CALL JobExecutor::elementReplaced( const css::container::ContainerEvent& ) throw(css::uno::RuntimeException)
{
    // I'm not interested on changed items :-)
}

//________________________________

/** @short  the used cfg changes notifier wish to be released in its reference.

    @descr  We close our internal used configuration instance to
            free this reference.

    @attention  For the special feature "bind global document event broadcaster to job execution"
                this job executor instance was registered from outside code as
                css.document.XEventListener. So it can be, that this disposing call comes from
                the global event broadcaster service. But we don't hold any reference to this service
                which can or must be released. Because this broadcaster itself is an one instance service
                too, we can ignore this request. On the other side we must relase our internal CFG
                reference ... SOLUTION => check the given event source and react only, if it's our internal
                hold configuration object!
 */
void SAL_CALL JobExecutor::disposing( const css::lang::EventObject& aEvent ) throw(css::uno::RuntimeException)
{
    /* SAFE { */
    ReadGuard aReadLock(m_aLock);
    css::uno::Reference< css::uno::XInterface > xCFG(m_aConfig.cfg(), css::uno::UNO_QUERY);
    if (
        (xCFG                == aEvent.Source        ) &&
        (m_aConfig.getMode() != ConfigAccess::E_CLOSED)
       )
    {
        m_aConfig.close();
    }
    aReadLock.unlock();
    /* } SAFE */
}

} // namespace framework

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>don't annoy us<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_framework.hxx"

//________________________________
//  my own includes
#include <jobs/jobexecutor.hxx>
#include <jobs/job.hxx>
#include <jobs/joburl.hxx>

#include <classes/converter.hxx>
#include <threadhelp/transactionguard.hxx>
#include <threadhelp/readguard.hxx>
#include <threadhelp/writeguard.hxx>
#include <general.h>
#include <services.h>

#include "helper/mischelper.hxx"

//________________________________
//  interface includes
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/container/XContainer.hpp>

//________________________________
//  includes of other projects
#include <unotools/configpathes.hxx>
#include <rtl/ustrbuf.hxx>
#include <vcl/svapp.hxx>

#include <rtl/logfile.hxx>

//________________________________
//  namespace

namespace framework{

//________________________________
//  non exported const

//________________________________
//  non exported definitions

//________________________________
//  declarations

DEFINE_XINTERFACE_6( JobExecutor                                                               ,
                     OWeakObject                                                               ,
                     DIRECT_INTERFACE(css::lang::XTypeProvider                                ),
                     DIRECT_INTERFACE(css::lang::XServiceInfo                                 ),
                     DIRECT_INTERFACE(css::task::XJobExecutor                                 ),
                     DIRECT_INTERFACE(css::container::XContainerListener                      ),
                     DIRECT_INTERFACE(css::document::XEventListener                           ),
                     DERIVED_INTERFACE(css::lang::XEventListener,css::document::XEventListener)
                   )

DEFINE_XTYPEPROVIDER_6( JobExecutor                       ,
                        css::lang::XTypeProvider          ,
                        css::lang::XServiceInfo           ,
                        css::task::XJobExecutor           ,
                        css::container::XContainerListener,
                        css::document::XEventListener     ,
                        css::lang::XEventListener
                      )

DEFINE_XSERVICEINFO_ONEINSTANCESERVICE( JobExecutor                   ,
                                        ::cppu::OWeakObject           ,
                                        SERVICENAME_JOBEXECUTOR       ,
                                        IMPLEMENTATIONNAME_JOBEXECUTOR
                                      )

DEFINE_INIT_SERVICE( JobExecutor,
                     {
                         m_xModuleManager = css::uno::Reference< css::frame::XModuleManager >(
                             m_xSMGR->createInstance(
                                 SERVICENAME_MODULEMANAGER ),
                             css::uno::UNO_QUERY_THROW );

                         /*Attention
                             I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
                             to create a new instance of this class by our own supported service factory.
                             see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
                         */
                        // read the list of all currently registered events inside configuration.
                        // e.g. "/org.openoffice.Office.Jobs/Events/<event name>"
                        // We need it later to check if an incoming event request can be executed successfully
                        // or must be rejected. It's an optimization! Of course we must implement updating of this
                        // list too ... Be listener at the configuration.

                        m_aConfig.open(ConfigAccess::E_READONLY);
                        if (m_aConfig.getMode() == ConfigAccess::E_READONLY)
                        {
                            css::uno::Reference< css::container::XNameAccess > xRegistry(m_aConfig.cfg(), css::uno::UNO_QUERY);
                            if (xRegistry.is())
                                m_lEvents = Converter::convert_seqOUString2OUStringList(xRegistry->getElementNames());

                            css::uno::Reference< css::container::XContainer > xNotifier(m_aConfig.cfg(), css::uno::UNO_QUERY);
                            if (xNotifier.is())
                            {
                                m_xConfigListener = new WeakContainerListener(this);
                                xNotifier->addContainerListener(m_xConfigListener);
                            }

                            // don't close cfg here!
                            // It will be done inside disposing ...
                        }
                     }
                   )

//________________________________

/**
    @short      standard ctor
    @descr      It initialize this new instance.

    @param      xSMGR
                    reference to the uno service manager
 */
JobExecutor::JobExecutor( /*IN*/ const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR )
    : ThreadHelpBase      (&Application::GetSolarMutex()                                   )
    , ::cppu::OWeakObject (                                                                )
    , m_xSMGR             (xSMGR                                                           )
    , m_xModuleManager    (                                                                )
    , m_aConfig           (xSMGR, ::rtl::OUString::createFromAscii(JobData::EVENTCFG_ROOT) )
{
    // Don't do any reference related code here! Do it inside special
    // impl_ method() ... see DEFINE_INIT_SERVICE() macro for further informations.
}

JobExecutor::~JobExecutor()
{
    css::uno::Reference< css::container::XContainer > xNotifier(m_aConfig.cfg(), css::uno::UNO_QUERY);
    if (xNotifier.is())
        xNotifier->removeContainerListener(m_xConfigListener);
}

//________________________________

/**
    @short  implementation of XJobExecutor interface
    @descr  We use the given event to locate any registered job inside our configuration
            and execute it. Further we control the lifetime of it and supress
            shutdown of the office till all jobs was finished.

    @param  sEvent
                is used to locate registered jobs
 */
void SAL_CALL JobExecutor::trigger( const ::rtl::OUString& sEvent ) throw(css::uno::RuntimeException)
{
    RTL_LOGFILE_CONTEXT(aLog, "fwk (as96863) JobExecutor::trigger()");

    /* SAFE { */
    ReadGuard aReadLock(m_aLock);

    // Optimization!
    // Check if the given event name exist inside configuration and reject wrong requests.
    // This optimization supress using of the cfg api for getting event and job descriptions ...
    if (m_lEvents.find(sEvent) == m_lEvents.end())
        return;

    // get list of all enabled jobs
    // The called static helper methods read it from the configuration and
    // filter disabled jobs using it's time stamp values.
    css::uno::Sequence< ::rtl::OUString > lJobs = JobData::getEnabledJobsForEvent(m_xSMGR, sEvent);

    aReadLock.unlock();
    /* } SAFE */

    // step over all enabled jobs and execute it
    sal_Int32 c = lJobs.getLength();
    for (sal_Int32 j=0; j<c; ++j)
    {
        /* SAFE { */
        aReadLock.lock();

        JobData aCfg(m_xSMGR);
        aCfg.setEvent(sEvent, lJobs[j]);
        aCfg.setEnvironment(JobData::E_EXECUTION);

        /*Attention!
            Jobs implements interfaces and dies by ref count!
            And freeing of such uno object is done by uno itself.
            So we have to use dynamic memory everytimes.
         */
        Job* pJob = new Job(m_xSMGR, css::uno::Reference< css::frame::XFrame >());
        css::uno::Reference< css::uno::XInterface > xJob(static_cast< ::cppu::OWeakObject* >(pJob), css::uno::UNO_QUERY);
        pJob->setJobData(aCfg);

        aReadLock.unlock();
        /* } SAFE */

        pJob->execute(css::uno::Sequence< css::beans::NamedValue >());
    }
}

//________________________________

void SAL_CALL JobExecutor::notifyEvent( const css::document::EventObject& aEvent ) throw(css::uno::RuntimeException)
{
    static ::rtl::OUString EVENT_ON_NEW             = DECLARE_ASCII("OnNew"             ); // Doc UI  event
    static ::rtl::OUString EVENT_ON_LOAD            = DECLARE_ASCII("OnLoad"            ); // Doc UI  event
    static ::rtl::OUString EVENT_ON_CREATE          = DECLARE_ASCII("OnCreate"          ); // Doc API event
    static ::rtl::OUString EVENT_ON_LOAD_FINISHED   = DECLARE_ASCII("OnLoadFinished"    ); // Doc API event
    static ::rtl::OUString EVENT_ON_DOCUMENT_OPENED = DECLARE_ASCII("onDocumentOpened"  ); // Job UI  event : OnNew    or OnLoad
    static ::rtl::OUString EVENT_ON_DOCUMENT_ADDED  = DECLARE_ASCII("onDocumentAdded"   ); // Job API event : OnCreate or OnLoadFinished

    /* SAFE { */
    ReadGuard aReadLock(m_aLock);

    ::comphelper::SequenceAsVector< JobData::TJob2DocEventBinding > lJobs;

    // Optimization!
    // Check if the given event name exist inside configuration and reject wrong requests.
    // This optimization supress using of the cfg api for getting event and job descriptions.
    // see using of m_lEvents.find() below ...

    // retrieve event context from event source
    rtl::OUString aModuleIdentifier;
    try
    {
        aModuleIdentifier = m_xModuleManager->identify( aEvent.Source );
    }
    catch( css::uno::Exception& )
    {}

    // Special feature: If the events "OnNew" or "OnLoad" occures - we generate our own event "onDocumentOpened".
    if (
        (aEvent.EventName.equals(EVENT_ON_NEW )) ||
        (aEvent.EventName.equals(EVENT_ON_LOAD))
       )
    {
        if (m_lEvents.find(EVENT_ON_DOCUMENT_OPENED) != m_lEvents.end())
            JobData::appendEnabledJobsForEvent(m_xSMGR, EVENT_ON_DOCUMENT_OPENED, lJobs);
    }

    // Special feature: If the events "OnCreate" or "OnLoadFinished" occures - we generate our own event "onDocumentAdded".
    if (
        (aEvent.EventName.equals(EVENT_ON_CREATE       )) ||
        (aEvent.EventName.equals(EVENT_ON_LOAD_FINISHED))
       )
    {
        if (m_lEvents.find(EVENT_ON_DOCUMENT_ADDED) != m_lEvents.end())
            JobData::appendEnabledJobsForEvent(m_xSMGR, EVENT_ON_DOCUMENT_ADDED, lJobs);
    }

    // Add all jobs for "real" notified event too .-)
    if (m_lEvents.find(aEvent.EventName) != m_lEvents.end())
        JobData::appendEnabledJobsForEvent(m_xSMGR, aEvent.EventName, lJobs);

    aReadLock.unlock();
    /* } SAFE */

    // step over all enabled jobs and execute it
    ::comphelper::SequenceAsVector< JobData::TJob2DocEventBinding >::const_iterator pIt;
    for (  pIt  = lJobs.begin();
           pIt != lJobs.end()  ;
         ++pIt                 )
    {
        /* SAFE { */
        aReadLock.lock();

        const JobData::TJob2DocEventBinding& rBinding = *pIt;

        JobData aCfg(m_xSMGR);
        aCfg.setEvent(rBinding.m_sDocEvent, rBinding.m_sJobName);
        aCfg.setEnvironment(JobData::E_DOCUMENTEVENT);

        if (!aCfg.hasCorrectContext(aModuleIdentifier))
            continue;

        /*Attention!
            Jobs implements interfaces and dies by ref count!
            And freeing of such uno object is done by uno itself.
            So we have to use dynamic memory everytimes.
         */
        css::uno::Reference< css::frame::XModel > xModel(aEvent.Source, css::uno::UNO_QUERY);
        Job* pJob = new Job(m_xSMGR, xModel);
        css::uno::Reference< css::uno::XInterface > xJob(static_cast< ::cppu::OWeakObject* >(pJob), css::uno::UNO_QUERY);
        pJob->setJobData(aCfg);

        aReadLock.unlock();
        /* } SAFE */

        pJob->execute(css::uno::Sequence< css::beans::NamedValue >());
    }
}

//________________________________

void SAL_CALL JobExecutor::elementInserted( const css::container::ContainerEvent& aEvent ) throw(css::uno::RuntimeException)
{
    ::rtl::OUString sValue;
    if (aEvent.Accessor >>= sValue)
    {
        ::rtl::OUString sEvent = ::utl::extractFirstFromConfigurationPath(sValue);
        if (sEvent.getLength() > 0)
        {
            OUStringList::iterator pEvent = m_lEvents.find(sEvent);
            if (pEvent == m_lEvents.end())
                m_lEvents.push_back(sEvent);
        }
    }
}

void SAL_CALL JobExecutor::elementRemoved ( const css::container::ContainerEvent& aEvent ) throw(css::uno::RuntimeException)
{
    ::rtl::OUString sValue;
    if (aEvent.Accessor >>= sValue)
    {
        ::rtl::OUString sEvent = ::utl::extractFirstFromConfigurationPath(sValue);
        if (sEvent.getLength() > 0)
        {
            OUStringList::iterator pEvent = m_lEvents.find(sEvent);
            if (pEvent != m_lEvents.end())
                m_lEvents.erase(pEvent);
        }
    }
}

void SAL_CALL JobExecutor::elementReplaced( const css::container::ContainerEvent& ) throw(css::uno::RuntimeException)
{
    // I'm not interested on changed items :-)
}

//________________________________

/** @short  the used cfg changes notifier wish to be released in its reference.

    @descr  We close our internal used configuration instance to
            free this reference.

    @attention  For the special feature "bind global document event broadcaster to job execution"
                this job executor instance was registered from outside code as
                css.document.XEventListener. So it can be, that this disposing call comes from
                the global event broadcaster service. But we don't hold any reference to this service
                which can or must be released. Because this broadcaster itself is an one instance service
                too, we can ignore this request. On the other side we must relase our internal CFG
                reference ... SOLUTION => check the given event source and react only, if it's our internal
                hold configuration object!
 */
void SAL_CALL JobExecutor::disposing( const css::lang::EventObject& aEvent ) throw(css::uno::RuntimeException)
{
    /* SAFE { */
    ReadGuard aReadLock(m_aLock);
    css::uno::Reference< css::uno::XInterface > xCFG(m_aConfig.cfg(), css::uno::UNO_QUERY);
    if (
        (xCFG                == aEvent.Source        ) &&
        (m_aConfig.getMode() != ConfigAccess::E_CLOSED)
       )
    {
        m_aConfig.close();
    }
    aReadLock.unlock();
    /* } SAFE */
}

} // namespace framework

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>#ifndef STAN_MATH_OPENCL_KERNELS_CHOLESKY_DECOMPOSE_HPP
#define STAN_MATH_OPENCL_KERNELS_CHOLESKY_DECOMPOSE_HPP
#ifdef STAN_OPENCL

#include <stan/math/opencl/kernel_cl.hpp>
#include <stan/math/opencl/buffer_types.hpp>

namespace stan {
namespace math {
namespace opencl_kernels {
// \cond
static const char *cholesky_decompose_kernel_code = STRINGIFY(
    // \endcond
    /**
     * Calculates the Cholesky Decomposition of a matrix on an OpenCL
     *
     * This kernel is run with threads organized in one dimension and
     * in a single thread block. The kernel is best suited for
     * small input matrices as it only utilizes a single streaming
     * multiprocessor. The kernels is used as a part of a blocked
     * cholesky decompose.
     *
     * @param[in, out] A The input matrix and the result of the cholesky
     *  decompisition
     * @param rows The number of rows for A and B.
     * @note Code is a const char* held in
     * cholesky_decompose_kernel_code.
     *  Used in math/opencl/cholesky_decompose.hpp.
     *  This kernel uses the helper macros available in helpers.cl.
     *
     */
    __kernel void cholesky_decompose(__global double *A, int rows) {
      const int local_index = get_local_id(0);
      // The following code is the sequential version of the inplace
      // cholesky decomposition. Only the innermost loops are parallelized. The
      // rows are processed sequentially. This loop process all the rows:
      for (int j = 0; j < rows; j++) {
        if (local_index == 0) {
          double sum = 0.0;
          for (int k = 0; k < j; k++) {
            sum = sum + A(j, k) * A(j, k);
          }
          A(j, j) = sqrt(A(j, j) - sum);
        }
        barrier(CLK_LOCAL_MEM_FENCE);
        if (local_index < j) {
          A(local_index, j) = 0.0;
        } else if (local_index > j) {
          double sum = 0.0;
          for (int k = 0; k < j; k++)
            sum = sum + A(local_index, k) * A(j, k);
          A(local_index, j) = (A(local_index, j) - sum) / A(j, j);
        }
        barrier(CLK_LOCAL_MEM_FENCE);
      }
    }
    // \cond
);
// \endcond

/**
 * See the docs for \link kernels/cholesky_decompose.hpp cholesky_decompose()
 * \endlink
 */
const kernel_cl<out_buffer, int> cholesky_decompose(
    "cholesky_decompose", {indexing_helpers, cholesky_decompose_kernel_code});

}  // namespace opencl_kernels
}  // namespace math
}  // namespace stan
#endif
#endif
<commit_msg>Fix typo<commit_after>#ifndef STAN_MATH_OPENCL_KERNELS_CHOLESKY_DECOMPOSE_HPP
#define STAN_MATH_OPENCL_KERNELS_CHOLESKY_DECOMPOSE_HPP
#ifdef STAN_OPENCL

#include <stan/math/opencl/kernel_cl.hpp>
#include <stan/math/opencl/buffer_types.hpp>

namespace stan {
namespace math {
namespace opencl_kernels {
// \cond
static const char *cholesky_decompose_kernel_code = STRINGIFY(
    // \endcond
    /**
     * Calculates the Cholesky Decomposition of a matrix on an OpenCL
     *
     * This kernel is run with threads organized in one dimension and
     * in a single thread block. The kernel is best suited for
     * small input matrices as it only utilizes a single streaming
     * multiprocessor. The kernels is used as a part of a blocked
     * cholesky decompose.
     *
     * @param[in, out] A The input matrix and the result of the cholesky
     *  decomposition
     * @param rows The number of rows for A and B.
     * @note Code is a const char* held in
     * cholesky_decompose_kernel_code.
     *  Used in math/opencl/cholesky_decompose.hpp.
     *  This kernel uses the helper macros available in helpers.cl.
     *
     */
    __kernel void cholesky_decompose(__global double *A, int rows) {
      const int local_index = get_local_id(0);
      // The following code is the sequential version of the inplace
      // cholesky decomposition. Only the innermost loops are parallelized. The
      // rows are processed sequentially. This loop process all the rows:
      for (int j = 0; j < rows; j++) {
        if (local_index == 0) {
          double sum = 0.0;
          for (int k = 0; k < j; k++) {
            sum = sum + A(j, k) * A(j, k);
          }
          A(j, j) = sqrt(A(j, j) - sum);
        }
        barrier(CLK_LOCAL_MEM_FENCE);
        if (local_index < j) {
          A(local_index, j) = 0.0;
        } else if (local_index > j) {
          double sum = 0.0;
          for (int k = 0; k < j; k++)
            sum = sum + A(local_index, k) * A(j, k);
          A(local_index, j) = (A(local_index, j) - sum) / A(j, j);
        }
        barrier(CLK_LOCAL_MEM_FENCE);
      }
    }
    // \cond
);
// \endcond

/**
 * See the docs for \link kernels/cholesky_decompose.hpp cholesky_decompose()
 * \endlink
 */
const kernel_cl<out_buffer, int> cholesky_decompose(
    "cholesky_decompose", {indexing_helpers, cholesky_decompose_kernel_code});

}  // namespace opencl_kernels
}  // namespace math
}  // namespace stan
#endif
#endif
<|endoftext|>