Logo Search packages:      
Sourcecode: mas version File versions

cdrom_unix_device.c

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

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#ifdef linux
#include <linux/cdrom.h>
#include <sys/ioctl.h>
#else
#include <sys/cdio.h>
#endif
#include "mas/mas_dpi.h"
#include "mas_cdrom_common.h"
#include "cdrom_int_device.h"
#include "profile.h"


static void _queue_ret_val( int32 reaction, int32 ret_val );

/* The head of the circular list */
struct cdrom_device head;


int32 mas_dev_init_library()
{
      /* Initialize the linked list */
      head.next = &head;
      head.prev = &head;

      return 1;
}


int32 mas_dev_init_instance(int32 device_instance, void* predicate)
{
      struct cdrom_device     *new_cd_dev;
      struct cdrom_device     *current_cd_dev;
      char              *device_location = (char*) predicate;
      int               ret_val;
      
      

      masc_entering_log_level("Instantiating cdrom device: mas_dev_init_instance()");

      /* If the device_location is null set it to point to "auto" */
      if(!device_location) device_location = "auto";

      /* Check that this device is not already open */
      current_cd_dev = head.next;
      while(current_cd_dev != &head)
      {
            if(strcmp(current_cd_dev->device_location, device_location) == 0)
            {
                  masc_log_message(MAS_VERBLVL_WARNING, "Device already instantiated: %s", device_location);
                  goto failure;
            }
            current_cd_dev = current_cd_dev->next;
      }

      /* Allocate space for the new struct */
      if((new_cd_dev = (struct cdrom_device*)calloc(1, sizeof(struct cdrom_device))) == NULL)
      {
            masc_log_message(MAS_VERBLVL_ERROR, "calloc returned NULL");
            goto failure;
      }

      /* Somewhere over the rainbow this will really autofind a cdrom */
      if(strcmp(device_location, "auto") == 0)
      {
#ifdef linux
            device_location = "/dev/cdrom";
#elif (defined sun)
            device_location = "/vol/dev/aliases/cdrom0";
#endif
      }

      /* Now open the cdrom */
      if((new_cd_dev->dev_handle = open(device_location, O_RDONLY)) == -1)
      {
            free(new_cd_dev);
            masc_log_message(MAS_VERBLVL_ERROR, "failed to open device: %s", strerror(errno));
            goto failure;
      }

      /* Add the device name to the device struct */
      if((new_cd_dev->device_location = (char*)malloc(strlen(device_location) + 1)) == NULL)
      {
            close(new_cd_dev->dev_handle);
            free(new_cd_dev);
            masc_log_message(MAS_VERBLVL_ERROR, "malloc returned NULL");
            goto failure;
      }
      strcpy(new_cd_dev->device_location, device_location);

      /* Set the instance number that created this device */
      new_cd_dev->instance = device_instance;

      /* Add the cdrom device to the linked list of cd devices */
      new_cd_dev->next = head.next;
      new_cd_dev->prev = &head;
      new_cd_dev->next->prev = new_cd_dev;
      head.next = new_cd_dev;

      /* Now update the info about the cd */
      if(!mas_cdrom_update_status(new_cd_dev))
      {
            mas_dev_exit_instance(device_instance, new_cd_dev);
            goto failure;
      }

      /* Get the reaction port */
      if(masd_get_port_by_name(device_instance, "reaction", &new_cd_dev->reaction_port) < 0)
      {
            masc_log_message(MAS_VERBLVL_ERROR, "Could not get MAS reaction port.");
            mas_dev_exit_instance(device_instance, new_cd_dev);
            goto failure;
      }

      ret_val = 1;
      goto success;
failure:
      ret_val = 0;

success:
      /* FIXME return success value when possible */
      masc_exiting_log_level();
      return ret_val;
}

int32 mas_dev_exit_instance(int32 device_instance, void* predicate)
{
      struct cdrom_device     *cd_dev;
      int               i;


      masc_entering_log_level("Exiting device instance: mas_dev_exit_instance()");

      /* If device_instance is -1 then this function is being called
       * internally with a pointer to a device. */
      if(device_instance == -1)
            cd_dev = (struct cdrom_device*)predicate;
      else
      {
            if((cd_dev = InstancetoCDDev(device_instance)) == NULL)
            {
                  masc_exiting_log_level();
                  return 0;
            }
      }

      /* Free and close the device resources */
      if(cd_dev->device_location) free(cd_dev->device_location);
      if(cd_dev->cd_genre) free(cd_dev->cd_genre);
      if(cd_dev->cd_title) free(cd_dev->cd_title);
      if(cd_dev->cd_year) free(cd_dev->cd_year);
      if(cd_dev->cd_misc_data) free(cd_dev->cd_misc_data);
      if(cd_dev->tracks)
      {
            for(i = 0; i <= cd_dev->number_of_tracks; i++)
                  if(cd_dev->tracks[i].trackname) free(cd_dev->tracks[i].trackname);
            free(cd_dev->tracks);
      }
      close(cd_dev->dev_handle);

      /* Now remove it from the linked list */
      cd_dev->prev->next = cd_dev->next;
      cd_dev->next->prev = cd_dev->prev;
      free(cd_dev);

      masc_exiting_log_level();
      return 1;
}

int32 mas_dev_exit_library()
{
      while(head.next != &head)
            mas_dev_exit_instance(-1, head.next);

      return 1;
}

int32 mas_dev_show_state(int32 device_instance, void* predicate)
{
      return 1;
}

int32 mas_cdrom_play_track(int32 device_instance, void* predicate)
{
      struct mas_package      package;
      struct cdrom_ti         ti;   /* Unix defined struct cdio.h */
      struct cdrom_device     *cd_dev = NULL;
      int               track;
      int               ret_val;



      masc_entering_log_level("Playing cdrom track: mas_cdrom_play_track()");

      /* Get the data from the mas package */
      masc_setup_package( &package, predicate, 0, MASC_PACKAGE_STATIC|MASC_PACKAGE_EXTRACT);
      masc_pull_int32(&package, &track);

      if((cd_dev = InstancetoCDDev(device_instance)) == NULL)
            goto failure;

      /* Make sure the cd info is up to date */
      if(!mas_cdrom_update_status(cd_dev))
            goto failure;

      /* Set the beginning track to play */
      if(track > cd_dev->number_of_tracks)
            ti.cdti_trk0 = 1;
      else
            ti.cdti_trk0 = track;

      /* Set the last track to play to the last one on the cd */
      ti.cdti_trk1 = cd_dev->number_of_tracks;

      /* Set the index to 1 */
      ti.cdti_ind0 = 1;
      ti.cdti_ind1 = 1;

      if(ioctl(cd_dev->dev_handle, CDROMPLAYTRKIND, &ti) == -1)
      {
            masc_log_message(MAS_VERBLVL_ERROR, "ioctl failed: %s", strerror(errno));
            goto failure;
      }

      /* Update the status from the new changes */
      if(!mas_cdrom_update_status(cd_dev))
            goto failure;

      ret_val = 1;
      goto success;
failure:
      ret_val = 0;
success:
      /* stuff the predicate package */
        masc_strike_package( &package );
        _queue_ret_val( cd_dev->reaction_port, ret_val );
      masc_exiting_log_level();
      return ret_val;
}

int32 mas_cdrom_play_msf(int32 device_instance, void* predicate)
{
      struct mas_package      package;
      struct cdrom_msf  msf;  /* Unix cdio.h defined struct */
      struct cdrom_device     *cd_dev;
      int               minute, second, frame;
      int               ret_val;


      masc_entering_log_level("Playing cdrom msf location: mas_cdrom_play_msf()");

      /* Get the data from the mas package */
      masc_setup_package(&package, predicate, 0, MASC_PACKAGE_STATIC|MASC_PACKAGE_EXTRACT);
      masc_pull_int32(&package, &minute);
      masc_pull_int32(&package, &second);
      masc_pull_int32(&package, &frame);
      
      if((cd_dev = InstancetoCDDev(device_instance)) == NULL)
            goto failure;

      /* Make sure the cd info is up to date */
      if(!mas_cdrom_update_status(cd_dev))
            goto failure;

      /* Set the starting time to play at */
      msf.cdmsf_min0 = minute;
      msf.cdmsf_sec0 = second;
      msf.cdmsf_frame0 = frame;

      /* Set the ending time to the end of the cd */
      msf.cdmsf_min1 = cd_dev->tracks[cd_dev->number_of_tracks].start_msf.minute;
      msf.cdmsf_sec1 = cd_dev->tracks[cd_dev->number_of_tracks].start_msf.second;
      msf.cdmsf_frame1 = cd_dev->tracks[cd_dev->number_of_tracks].start_msf.frame;

      if(ioctl(cd_dev->dev_handle, CDROMPLAYMSF, &msf) == -1)
      {
            masc_log_message(MAS_VERBLVL_ERROR, "ioctl failed: %s", strerror(errno));
            goto failure;
      }

      /* Make sure the cd info is up to date */
      if(!mas_cdrom_update_status(cd_dev))
            goto failure;

      ret_val = 1;
      goto success;
failure:
      ret_val = 0;
success:
      /* stuff the predicate package */
        masc_strike_package( &package );
        _queue_ret_val( cd_dev->reaction_port, ret_val );
      masc_exiting_log_level();
      return ret_val;
}

int mas_cdrom_update_status(struct cdrom_device *cd_dev)
{
      struct cdrom_subchnl    subchnl; /* Unix defined struct cdio.h */


      masc_entering_log_level("Updating cdrom status: mas_cdrom_update_status()");

      /* Check if the cdrom was closed and reopen it if neccessary. */
      if(cd_dev->dev_handle == -1)
      {
            if((cd_dev->dev_handle = open(cd_dev->device_location, O_RDONLY)) == -1)
            {
                  masc_log_message(MAS_VERBLVL_ERROR, "Failed to reopen cdrom: %s", strerror(errno));
                  masc_exiting_log_level();
                  return 0;
            }
      }

      /* Get the status of the cdrom */
      subchnl.cdsc_format = CDROM_MSF;
      if(ioctl(cd_dev->dev_handle, CDROMSUBCHNL, &subchnl) == -1)
      {
            masc_log_message(MAS_VERBLVL_ERROR, "ioctl failed: %s", strerror(errno));
            masc_exiting_log_level();
            return 0;
      }

      /* Set the current status of the cdrom */
      switch(subchnl.cdsc_audiostatus)
      {
            case CDROM_AUDIO_PLAY:
                  cd_dev->status = CDROM_PLAY;
                  break;
            case CDROM_AUDIO_PAUSED:
                  cd_dev->status = CDROM_PAUSE;
                  break;
            case CDROM_AUDIO_COMPLETED:
                  cd_dev->status = CDROM_COMPLETE;
                  break;
            case CDROM_AUDIO_INVALID:
            case CDROM_AUDIO_NO_STATUS:
            case CDROM_AUDIO_ERROR:
                  cd_dev->status = CDROM_STOP;
                  break;
            default:
                  cd_dev->status = CDROM_ERROR;
      }

      /* Set the current playing track */
      cd_dev->current_track = subchnl.cdsc_trk;

      /* Set the addresses of the current track */
      cd_dev->absolute_msf.minute = subchnl.cdsc_absaddr.msf.minute;
      cd_dev->absolute_msf.second = subchnl.cdsc_absaddr.msf.second;
      cd_dev->absolute_msf.frame = subchnl.cdsc_absaddr.msf.frame;

      cd_dev->relative_msf.minute = subchnl.cdsc_reladdr.msf.minute;
      cd_dev->relative_msf.second = subchnl.cdsc_reladdr.msf.second;
      cd_dev->relative_msf.frame = subchnl.cdsc_reladdr.msf.frame;

      /* Now update the track information */
      if(!mas_dev_read_track_info(cd_dev))
      {
            masc_exiting_log_level();
            return 0;
      }

      masc_exiting_log_level();
      return 1;
}

int32 mas_cdrom_set_status(int32 device_instance, void* predicate)
{
      struct cdrom_device     *cd_dev;
      struct mas_package      package;
      int               state;
      int               cd_status;
      int               ret_val;


      masc_entering_log_level("Setting cdrom status: mas_cdrom_set_status()");

      /* Get the data from the mas package */
      masc_setup_package(&package, predicate, 0, MASC_PACKAGE_STATIC|MASC_PACKAGE_EXTRACT);
      masc_pull_int32(&package, &cd_status);

      if((cd_dev = InstancetoCDDev(device_instance)) == NULL)
            goto failure;

      /* Find which state to change to */
      switch(cd_status)
      {
            case CDROM_PLAY:
                  state = CDROMPAUSE;
                  break;
            case CDROM_PAUSE:
                  state = CDROMPAUSE;
                  break;
            case CDROM_RESUME:
                  state = CDROMRESUME;
                  break;
            case CDROM_STOP:
                  state = CDROMSTOP;
                  break;
            case CDROM_EJECT:
                  state = CDROMEJECT;
                  break;
            default:
                  goto failure;
      }

      if(ioctl(cd_dev->dev_handle, state, 0) == -1)
      {
            masc_log_message(MAS_VERBLVL_ERROR, "ioctl failed: %s", strerror(errno));
            goto failure;
      }

      /* If the cdrom was eject it needs to be closed also */
      if(state == CDROMEJECT)
      {
            close(cd_dev->dev_handle);
            cd_dev->dev_handle = -1;
      }

      ret_val = 1;
      goto success;
failure:
      ret_val = 0;
success:
      /* stuff the predicate package */
        masc_strike_package( &package );
        _queue_ret_val( cd_dev->reaction_port, ret_val );
      masc_exiting_log_level();
      return ret_val;
}

int32 mas_cdrom_get_info(int32 device_instance, void* predicate)
{
      struct mas_package      package;
      struct cdrom_device     *cd_dev;
      int               ret_val = 1;
      int               query_cddb;
      int               i;
      char              *username = NULL, *servername = NULL;


      masc_entering_log_level("Getting cdrom information: mas_cdrom_get_info()");

      /* Make sure the cd info is up to date */
      if((cd_dev = InstancetoCDDev(device_instance)) == NULL)
            ret_val = 0;
      else if(!mas_cdrom_update_status(cd_dev))
            ret_val = 0;

      /* Get the data from the mas package */
      masc_setup_package(&package, predicate, 0, MASC_PACKAGE_STATIC|MASC_PACKAGE_EXTRACT);
      masc_pull_int32(&package, &query_cddb);

      /* If query_cddb is true then get the cddb info */
      if(ret_val && query_cddb)
      {
            masc_pull_string(&package, &servername, FALSE);
            masc_pull_string(&package, &username, FALSE);
            /* Check if the cddb update fails */
            if(!update_cddb_info(cd_dev, username, servername))
                  /* Set ret_val to 1 indicating only the track info is being sent. */
                  ret_val = 1;
            else
                  /* Set ret_val to 2 indicating cddb data and track info is being sent */
                  ret_val = 2;
      }

      /* stuff the predicate package */
        masc_setup_package(&package, NULL, 0, MASC_PACKAGE_NOFREE );

      masc_push_int32(&package, ret_val);
      if(ret_val)
      {
            /* First push the cd track info */
            masc_push_int32(&package, cd_dev->number_of_tracks);
            for(i=0; i<cd_dev->number_of_tracks; i++)
            {
                  masc_push_int32(&package, cd_dev->tracks[i].start_msf.minute);
                  masc_push_int32(&package, cd_dev->tracks[i].start_msf.second);
                  masc_push_int32(&package, cd_dev->tracks[i].start_msf.frame);
                  masc_push_int32(&package, cd_dev->tracks[i].length_msf.minute);
                  masc_push_int32(&package, cd_dev->tracks[i].length_msf.second);
                  masc_push_int32(&package, cd_dev->tracks[i].length_msf.frame);
            }
            /* Push the cddb info if needed */
            if(ret_val == 2)
            {
                  masc_push_int32(&package, cd_dev->cddb_id);
                  masc_push_string(&package, cd_dev->cd_title);
                  masc_push_string(&package, cd_dev->cd_genre);
                  masc_push_string(&package, cd_dev->cd_year);
                  masc_push_string(&package, cd_dev->cd_misc_data);
                  for(i=0; i<cd_dev->number_of_tracks; i++)
                        masc_push_string(&package, cd_dev->tracks[i].trackname);
            }
      }
      
      /* Send the package off */
      masc_finalize_package(&package);
      masd_reaction_queue_response(cd_dev->reaction_port, package.contents, package.size);
        masc_strike_package( &package );

      masc_exiting_log_level();
      return ret_val;

}

int32 mas_cdrom_get_status(int32 device_instance, void* predicate)
{
      struct mas_package      package;
      struct cdrom_device     *cd_dev;
      int               ret_val = 1;


      masc_entering_log_level("Getting cdrom status: mas_cdrom_get_status()");

      /* Make sure the cd info is up to date */
      if((cd_dev = InstancetoCDDev(device_instance)) == NULL)
            ret_val = 0;
      else if(!mas_cdrom_update_status(cd_dev))
            ret_val = 0;

      /* stuff the predicate package */
        masc_setup_package( &package, NULL, 0, MASC_PACKAGE_NOFREE );
      masc_push_int32(&package, ret_val);
      if(ret_val)
      {
            if(cd_dev->device_location) masc_push_string(&package, cd_dev->device_location);
            masc_push_int32(&package, cd_dev->status);
            masc_push_int32(&package, cd_dev->current_track);
            masc_push_int32(&package, cd_dev->absolute_msf.minute);
            masc_push_int32(&package, cd_dev->absolute_msf.second);
            masc_push_int32(&package, cd_dev->absolute_msf.frame);
            masc_push_int32(&package, cd_dev->relative_msf.minute);
            masc_push_int32(&package, cd_dev->relative_msf.second);
            masc_push_int32(&package, cd_dev->relative_msf.frame);
      }
      
      /* Now send the package off */
      masc_finalize_package(&package);
      masd_reaction_queue_response(cd_dev->reaction_port, package.contents, package.size);
      masc_strike_package(&package);

      masc_exiting_log_level();
      return ret_val;
}

int mas_dev_read_track_info(struct cdrom_device* cd_dev)
{
      struct cdrom_tochdr     toc; /* Unix defined struct cdio.h */
      struct cdrom_tocentry   tocentry; /* Unix defined struct cdio.h */
      int               track;



      masc_entering_log_level("Reading track information: mas_dev_read_track_info()");

      /* Get the table of contents for the cd */
      if(ioctl(cd_dev->dev_handle, CDROMREADTOCHDR, &toc) == -1)
      {
            masc_log_message(MAS_VERBLVL_ERROR, "ioctl failed: %s", strerror(errno));
            if(cd_dev->tracks) free(cd_dev->tracks);
            cd_dev->tracks = NULL;
            masc_exiting_log_level();
            return 0;
      }


      /* Get the number of tracks on the cd */
      cd_dev->number_of_tracks = toc.cdth_trk1 - toc.cdth_trk0 + 1;
      if(cd_dev->number_of_tracks <= 0)
      {
            masc_log_message(MAS_VERBLVL_ERROR, "Number of tracks reported was: %d", cd_dev->number_of_tracks);
            if(cd_dev->tracks) free(cd_dev->tracks);
            cd_dev->tracks = NULL;
            masc_exiting_log_level();
            return 0;
      }

      /* Allocate memory to hold all the track info + the lead out track. */
      if(cd_dev->tracks)
      {     
            free(cd_dev->tracks);
            cd_dev->tracks = NULL;
      }
      if((cd_dev->tracks = (struct track_info*)calloc(cd_dev->number_of_tracks + 2, sizeof(struct track_info))) == NULL)
      {
            masc_log_message(MAS_VERBLVL_ERROR, "calloc returned NULL");
            masc_exiting_log_level();
            return 0;
      }
      
      /* Now fill in all the individual track data */
      tocentry.cdte_format = CDROM_MSF;
      for(track = 0; track < cd_dev->number_of_tracks; track++)
      {
            /* Add the track offset to the first track number */
            tocentry.cdte_track = track + toc.cdth_trk0;

            if(ioctl(cd_dev->dev_handle, CDROMREADTOCENTRY, &tocentry) == -1)
            {
                  masc_log_message(MAS_VERBLVL_ERROR, "ioctl failed: %s", strerror(errno));
                  free(cd_dev->tracks);
                  cd_dev->tracks = NULL;
                  masc_exiting_log_level();
                  return 0;
            }

            /* Fill in the tracks info */
            cd_dev->tracks[track].number = tocentry.cdte_track;
            cd_dev->tracks[track].audio_track = tocentry.cdte_ctrl != CDROM_DATA_TRACK;

            cd_dev->tracks[track].start_msf.minute = tocentry.cdte_addr.msf.minute;
            cd_dev->tracks[track].start_msf.second = tocentry.cdte_addr.msf.second;
            cd_dev->tracks[track].start_msf.frame = tocentry.cdte_addr.msf.frame;
      }

      /* Get the cdroms leadout */
      tocentry.cdte_track = CDROM_LEADOUT;
      tocentry.cdte_format = CDROM_MSF;
      if(ioctl(cd_dev->dev_handle, CDROMREADTOCENTRY, &tocentry) == -1) 
      {
            masc_log_message(MAS_VERBLVL_ERROR, "ioctl failed: %s", strerror(errno));
            free(cd_dev->tracks);
            cd_dev->tracks = NULL;
            masc_exiting_log_level();
            return 0;
      }

      cd_dev->tracks[track].number = track + toc.cdth_trk0;
      cd_dev->tracks[track].audio_track = 0;
      cd_dev->tracks[track].start_msf.minute = tocentry.cdte_addr.msf.minute;
      cd_dev->tracks[track].start_msf.second = tocentry.cdte_addr.msf.second;
      cd_dev->tracks[track].start_msf.frame = tocentry.cdte_addr.msf.frame;

      /* Now calculate all the track lengths using the absolute track values */
      for(track = 0; track < cd_dev->number_of_tracks; track++)
      {
            cd_dev->tracks[track].length_msf.minute = cd_dev->tracks[track+1].start_msf.minute - cd_dev->tracks[track].start_msf.minute;
            cd_dev->tracks[track].length_msf.second = cd_dev->tracks[track+1].start_msf.second - cd_dev->tracks[track].start_msf.second;
            cd_dev->tracks[track].length_msf.frame = cd_dev->tracks[track+1].start_msf.frame - cd_dev->tracks[track].start_msf.frame;

            if(cd_dev->tracks[track].length_msf.frame < 0)
            {
                  cd_dev->tracks[track].length_msf.second --;
                  cd_dev->tracks[track].length_msf.frame += 75;
            }

            if(cd_dev->tracks[track].length_msf.second < 0)
            {
                  cd_dev->tracks[track].length_msf.minute --;
                  cd_dev->tracks[track].length_msf.second += 60;
            }

      }

      masc_exiting_log_level();
      return 1;
}

struct cdrom_device *InstancetoCDDev(int instance)
{
      struct cdrom_device     *current = &head;


      masc_entering_log_level("Looking up the cdrom device related to instance number: InstancetoCDDev()");

      while(current->next != &head && current->instance != instance)
            current = current->next;

      if(current != &head)
      {
            masc_exiting_log_level();
            return current;
      }
      else
      {
            masc_log_message(MAS_VERBLVL_ERROR, "No cdrom device for the given instance number: %d", instance);
            masc_exiting_log_level();
            return NULL;
      }
}

void
_queue_ret_val( int32 reaction, int32 ret_val )
{
    struct mas_package package;
    
    /* stuff the predicate package */
    masc_setup_package( &package, NULL, 0, MASC_PACKAGE_NOFREE );
    masc_push_int32( &package, ret_val);
    masc_finalize_package( &package);
    
    masd_reaction_queue_response(reaction, package.contents, package.size);
    masc_strike_package(&package);
}


Generated by  Doxygen 1.6.0   Back to index