summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rondeau <trondeau@vt.edu>2013-03-10 22:48:39 -0400
committerTom Rondeau <trondeau@vt.edu>2013-03-10 22:48:39 -0400
commit5a3f0062fa438875b68191363d4ff78ccd07d0c9 (patch)
tree9f883de47cc6ce1535d0a91219fbd0511d56acf8
parent1bc6349e4714c5c4856b3abb95dc5f6b15c44281 (diff)
parent45f9c0a5792526279ebf5ffa6a4853c7e2de6dd6 (diff)
Merge branch 'master' into next
-rw-r--r--gr-blocks/grc/blocks_block_tree.xml3
-rw-r--r--gr-blocks/grc/blocks_file_descriptor_sink.xml59
-rw-r--r--gr-blocks/grc/blocks_file_descriptor_source.xml73
-rw-r--r--gr-blocks/grc/blocks_file_sink.xml78
-rw-r--r--gr-blocks/include/blocks/CMakeLists.txt4
-rw-r--r--gr-blocks/include/blocks/file_descriptor_sink.h54
-rw-r--r--gr-blocks/include/blocks/file_descriptor_source.h61
-rw-r--r--gr-blocks/include/blocks/file_sink.h55
-rw-r--r--gr-blocks/include/blocks/file_sink_base.h80
-rw-r--r--gr-blocks/lib/CMakeLists.txt4
-rw-r--r--gr-blocks/lib/file_descriptor_sink_impl.cc94
-rw-r--r--gr-blocks/lib/file_descriptor_sink_impl.h49
-rw-r--r--gr-blocks/lib/file_descriptor_source_impl.cc156
-rw-r--r--gr-blocks/lib/file_descriptor_source_impl.h58
-rw-r--r--gr-blocks/lib/file_sink_base.cc131
-rw-r--r--gr-blocks/lib/file_sink_impl.cc90
-rw-r--r--gr-blocks/lib/file_sink_impl.h48
-rw-r--r--gr-blocks/python/qa_file_source_sink.py93
-rw-r--r--gr-blocks/swig/blocks_swig.i11
19 files changed, 1201 insertions, 0 deletions
diff --git a/gr-blocks/grc/blocks_block_tree.xml b/gr-blocks/grc/blocks_block_tree.xml
index 573558466d..124cbe651f 100644
--- a/gr-blocks/grc/blocks_block_tree.xml
+++ b/gr-blocks/grc/blocks_block_tree.xml
@@ -31,6 +31,7 @@
<cat>
<name>Sources (New)</name>
<block>blocks_file_source</block>
+ <block>blocks_file_descriptor_source</block>
<block>blocks_file_meta_source</block>
<block>blocks_pdu_to_tagged_stream</block>
<block>blocks_random_pdu</block>
@@ -40,6 +41,8 @@
</cat>
<cat>
<name>Sinks (New)</name>
+ <block>blocks_file_sink</block>
+ <block>blocks_file_descriptor_sink</block>
<block>blocks_file_meta_sink</block>
<block>blocks_tagged_stream_to_pdu</block>
<block>blocks_tag_debug</block>
diff --git a/gr-blocks/grc/blocks_file_descriptor_sink.xml b/gr-blocks/grc/blocks_file_descriptor_sink.xml
new file mode 100644
index 0000000000..211d86dfd3
--- /dev/null
+++ b/gr-blocks/grc/blocks_file_descriptor_sink.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##File Sink
+###################################################
+ -->
+<block>
+ <name>File Descriptor Sink</name>
+ <key>blocks_file_descriptor_sink</key>
+ <import>from gnuradio import blocks</import>
+ <make>blocks.file_descriptor_sink($type.size*$vlen, $fd)</make>
+ <param>
+ <name>File Descriptor</name>
+ <key>fd</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Input Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </sink>
+</block>
diff --git a/gr-blocks/grc/blocks_file_descriptor_source.xml b/gr-blocks/grc/blocks_file_descriptor_source.xml
new file mode 100644
index 0000000000..b29335c3af
--- /dev/null
+++ b/gr-blocks/grc/blocks_file_descriptor_source.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##File Source
+###################################################
+ -->
+<block>
+ <name>File Descriptor Source</name>
+ <key>blocks_file_descriptor_source</key>
+ <import>from gnuradio import blocks</import>
+ <make>blocks.file_descriptor_source($type.size*$vlen, $fd, $repeat)</make>
+ <param>
+ <name>File Descriptor</name>
+ <key>fd</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Output Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Repeat</name>
+ <key>repeat</key>
+ <value>True</value>
+ <type>enum</type>
+ <option>
+ <name>Yes</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>No</name>
+ <key>False</key>
+ </option>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen &gt; 0</check>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
diff --git a/gr-blocks/grc/blocks_file_sink.xml b/gr-blocks/grc/blocks_file_sink.xml
new file mode 100644
index 0000000000..75ef86a6b8
--- /dev/null
+++ b/gr-blocks/grc/blocks_file_sink.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##File Sink
+###################################################
+ -->
+<block>
+ <name>File Sink</name>
+ <key>blocks_file_sink</key>
+ <import>from gnuradio import blocks</import>
+ <make>blocks.file_sink($type.size*$vlen, $file)
+self.$(id).set_unbuffered($unbuffered)</make>
+ <callback>set_unbuffered($unbuffered)</callback>
+ <callback>open($file)</callback>
+ <param>
+ <name>File</name>
+ <key>file</key>
+ <value></value>
+ <type>file_save</type>
+ </param>
+ <param>
+ <name>Input Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Unbuffered</name>
+ <key>unbuffered</key>
+ <value>False</value>
+ <type>bool</type>
+ <option>
+ <name>Off</name>
+ <key>False</key>
+ </option>
+ <option>
+ <name>On</name>
+ <key>True</key>
+ </option>
+ </param>
+
+ <check>$vlen &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </sink>
+</block>
diff --git a/gr-blocks/include/blocks/CMakeLists.txt b/gr-blocks/include/blocks/CMakeLists.txt
index 3315430a5f..5cc2731cb1 100644
--- a/gr-blocks/include/blocks/CMakeLists.txt
+++ b/gr-blocks/include/blocks/CMakeLists.txt
@@ -101,6 +101,7 @@ install(FILES
api.h
control_loop.h
count_bits.h
+ file_sink_base.h
fxpt.h
fxpt_nco.h
fxpt_vco.h
@@ -123,6 +124,9 @@ install(FILES
conjugate_cc.h
deinterleave.h
delay.h
+ file_descriptor_sink.h
+ file_descriptor_source.h
+ file_sink.h
file_source.h
file_meta_sink.h
file_meta_source.h
diff --git a/gr-blocks/include/blocks/file_descriptor_sink.h b/gr-blocks/include/blocks/file_descriptor_sink.h
new file mode 100644
index 0000000000..df59e24c0a
--- /dev/null
+++ b/gr-blocks/include/blocks/file_descriptor_sink.h
@@ -0,0 +1,54 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GR_FILE_DESCRIPTOR_SINK_H
+#define INCLUDED_GR_FILE_DESCRIPTOR_SINK_H
+
+#include <blocks/api.h>
+#include <gr_sync_block.h>
+
+namespace gr {
+ namespace blocks {
+
+ /*!
+ * \brief Write stream to file descriptor.
+ * \ingroup sink_blk
+ */
+ class BLOCKS_API file_descriptor_sink : virtual public gr_sync_block
+ {
+ public:
+ // gr::blocks::file_descriptor_sink::sptr
+ typedef boost::shared_ptr<file_descriptor_sink> sptr;
+
+ /*!
+ * Build a file descriptor sink block.
+ *
+ * \param itemsize item size of the incoming data stream.
+ * \param fd file descriptor (as an integer).
+ */
+ static sptr make(size_t itemsize, int fd);
+ };
+
+ } /* namespace blocks */
+} /* namespace gr */
+
+#endif /* INCLUDED_GR_FILE_DESCRIPTOR_SINK_H */
diff --git a/gr-blocks/include/blocks/file_descriptor_source.h b/gr-blocks/include/blocks/file_descriptor_source.h
new file mode 100644
index 0000000000..ff4f14792b
--- /dev/null
+++ b/gr-blocks/include/blocks/file_descriptor_source.h
@@ -0,0 +1,61 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GR_FILE_DESCRIPTOR_SOURCE_H
+#define INCLUDED_GR_FILE_DESCRIPTOR_SOURCE_H
+
+#include <blocks/api.h>
+#include <gr_sync_block.h>
+
+
+namespace gr {
+ namespace blocks {
+
+ /*!
+ * \brief Read stream from file descriptor.
+ * \ingroup source_blk
+ */
+ class BLOCKS_API file_descriptor_source : virtual public gr_sync_block
+ {
+ protected:
+ virtual int read_items(char *buf, int nitems) = 0;
+ virtual int handle_residue(char *buf, int nbytes_read) = 0;
+ virtual void flush_residue() = 0;
+
+ public:
+ // gr::blocks::file_descriptor_source::sptr
+ typedef boost::shared_ptr<file_descriptor_source> sptr;
+
+ /*!
+ * Build a file descriptor source block.
+ *
+ * \param itemsize item size of the incoming data stream.
+ * \param fd file descriptor (as an integer).
+ * \param repeat repeat the data stream continuously.
+ */
+ static sptr make(size_t itemsize, int fd, bool repeat);
+ };
+
+ } /* namespace blocks */
+} /* namespace gr */
+
+#endif /* INCLUDED_GR_FILE_DESCRIPTOR_SOURCE_H */
diff --git a/gr-blocks/include/blocks/file_sink.h b/gr-blocks/include/blocks/file_sink.h
new file mode 100644
index 0000000000..08c2adf1f7
--- /dev/null
+++ b/gr-blocks/include/blocks/file_sink.h
@@ -0,0 +1,55 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2007,2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GR_FILE_SINK_H
+#define INCLUDED_GR_FILE_SINK_H
+
+#include <blocks/api.h>
+#include <blocks/file_sink_base.h>
+#include <gr_sync_block.h>
+
+namespace gr {
+ namespace blocks {
+
+ /*!
+ * \brief Write stream to file.
+ * \ingroup sink_blk
+ */
+ class BLOCKS_API file_sink : virtual public gr_sync_block,
+ virtual public file_sink_base
+ {
+ public:
+ // gr::blocks::file_sink::sptr
+ typedef boost::shared_ptr<file_sink> sptr;
+
+ /*!
+ * \brief Make a file sink.
+ * \param itemsize size of the input data items.
+ * \param filename name of the file to open and write output to.
+ */
+ static sptr make(size_t itemsize, const char *filename);
+ };
+
+ } /* namespace blocks */
+} /* namespace gr */
+
+#endif /* INCLUDED_GR_FILE_SINK_H */
diff --git a/gr-blocks/include/blocks/file_sink_base.h b/gr-blocks/include/blocks/file_sink_base.h
new file mode 100644
index 0000000000..3eeb0e63da
--- /dev/null
+++ b/gr-blocks/include/blocks/file_sink_base.h
@@ -0,0 +1,80 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2007,2008,2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GR_FILE_SINK_BASE_H
+#define INCLUDED_GR_FILE_SINK_BASE_H
+
+#include <blocks/api.h>
+#include <boost/thread.hpp>
+#include <cstdio>
+
+namespace gr {
+ namespace blocks {
+
+ /*!
+ * \brief Common base class for file sinks
+ */
+ class BLOCKS_API file_sink_base
+ {
+ protected:
+ FILE *d_fp; // current FILE pointer
+ FILE *d_new_fp; // new FILE pointer
+ bool d_updated; // is there a new FILE pointer?
+ bool d_is_binary;
+ boost::mutex d_mutex;
+ bool d_unbuffered;
+
+ protected:
+ file_sink_base(const char *filename, bool is_binary);
+
+ public:
+ file_sink_base() {}
+ ~file_sink_base();
+
+ /*!
+ * \brief Open filename and begin output to it.
+ */
+ bool open(const char *filename);
+
+ /*!
+ * \brief Close current output file.
+ *
+ * Closes current output file and ignores any output until
+ * open is called to connect to another file.
+ */
+ void close();
+
+ /*!
+ * \brief if we've had an update, do it now.
+ */
+ void do_update();
+
+ /*!
+ * \brief turn on unbuffered writes for slower outputs
+ */
+ void set_unbuffered(bool unbuffered);
+ };
+
+ } /* namespace blocks */
+} /* namespace gr */
+
+#endif /* INCLUDED_GR_FILE_SINK_BASE_H */
diff --git a/gr-blocks/lib/CMakeLists.txt b/gr-blocks/lib/CMakeLists.txt
index c1a6e55738..7e429a8d1b 100644
--- a/gr-blocks/lib/CMakeLists.txt
+++ b/gr-blocks/lib/CMakeLists.txt
@@ -143,6 +143,7 @@ list(APPEND gr_blocks_sources
${generated_sources}
control_loop.cc
count_bits.cc
+ file_sink_base.cc
fxpt.cc
wavfile.cc
add_ff_impl.cc
@@ -160,6 +161,9 @@ list(APPEND gr_blocks_sources
conjugate_cc_impl.cc
deinterleave_impl.cc
delay_impl.cc
+ file_descriptor_sink_impl.cc
+ file_descriptor_source_impl.cc
+ file_sink_impl.cc
file_source_impl.cc
file_meta_sink_impl.cc
file_meta_source_impl.cc
diff --git a/gr-blocks/lib/file_descriptor_sink_impl.cc b/gr-blocks/lib/file_descriptor_sink_impl.cc
new file mode 100644
index 0000000000..a1f26220d2
--- /dev/null
+++ b/gr-blocks/lib/file_descriptor_sink_impl.cc
@@ -0,0 +1,94 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2010,2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "file_descriptor_sink_impl.h"
+#include <gr_io_signature.h>
+#include <cstdio>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdexcept>
+#include <stdio.h>
+
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
+
+namespace gr {
+ namespace blocks {
+
+ file_descriptor_sink::sptr
+ file_descriptor_sink::make(size_t itemsize, int fd)
+ {
+ return gnuradio::get_initial_sptr
+ (new file_descriptor_sink_impl(itemsize, fd));
+ }
+
+ file_descriptor_sink_impl::file_descriptor_sink_impl(size_t itemsize, int fd)
+ : gr_sync_block("file_descriptor_sink",
+ gr_make_io_signature(1, 1, itemsize),
+ gr_make_io_signature(0, 0, 0)),
+ d_itemsize(itemsize), d_fd(fd)
+ {
+ }
+
+ file_descriptor_sink_impl::~file_descriptor_sink_impl()
+ {
+ close(d_fd);
+ }
+
+ int
+ file_descriptor_sink_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ char *inbuf = (char*)input_items[0];
+ unsigned long byte_size = noutput_items * d_itemsize;
+
+ while(byte_size > 0) {
+ ssize_t r;
+
+ r = write(d_fd, inbuf, byte_size);
+ if(r == -1) {
+ if(errno == EINTR)
+ continue;
+ else {
+ perror("file_descriptor_sink");
+ return -1; // indicate we're done
+ }
+ }
+ else {
+ byte_size -= r;
+ inbuf += r;
+ }
+ }
+
+ return noutput_items;
+ }
+
+ } /* namespace blocks */
+} /* namespace gr */
diff --git a/gr-blocks/lib/file_descriptor_sink_impl.h b/gr-blocks/lib/file_descriptor_sink_impl.h
new file mode 100644
index 0000000000..90b02f4163
--- /dev/null
+++ b/gr-blocks/lib/file_descriptor_sink_impl.h
@@ -0,0 +1,49 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GR_FILE_DESCRIPTOR_SINK_IMPL_H
+#define INCLUDED_GR_FILE_DESCRIPTOR_SINK_IMPL_H
+
+#include <blocks/file_descriptor_sink.h>
+
+namespace gr {
+ namespace blocks {
+
+ class file_descriptor_sink_impl : public file_descriptor_sink
+ {
+ private:
+ size_t d_itemsize;
+ int d_fd;
+
+ public:
+ file_descriptor_sink_impl(size_t itemsize, int fd);
+ ~file_descriptor_sink_impl();
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace blocks */
+} /* namespace gr */
+
+#endif /* INCLUDED_GR_FILE_DESCRIPTOR_SINK_IMPL_H */
diff --git a/gr-blocks/lib/file_descriptor_source_impl.cc b/gr-blocks/lib/file_descriptor_source_impl.cc
new file mode 100644
index 0000000000..667e96b7fa
--- /dev/null
+++ b/gr-blocks/lib/file_descriptor_source_impl.cc
@@ -0,0 +1,156 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2005,2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "file_descriptor_source_impl.h"
+#include <gr_io_signature.h>
+#include <cstdio>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdexcept>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
+
+namespace gr {
+ namespace blocks {
+
+ file_descriptor_source::sptr
+ file_descriptor_source::make(size_t itemsize, int fd, bool repeat)
+ {
+ return gnuradio::get_initial_sptr
+ (new file_descriptor_source_impl(itemsize, fd, repeat));
+ }
+
+ file_descriptor_source_impl::file_descriptor_source_impl(size_t itemsize,
+ int fd,
+ bool repeat)
+ : gr_sync_block("file_descriptor_source",
+ gr_make_io_signature(0, 0, 0),
+ gr_make_io_signature(1, 1, itemsize)),
+ d_itemsize(itemsize), d_fd(fd), d_repeat(repeat),
+ d_residue(new unsigned char[itemsize]), d_residue_len (0)
+ {
+ }
+
+ file_descriptor_source_impl::~file_descriptor_source_impl()
+ {
+ close(d_fd);
+ delete [] d_residue;
+ }
+
+ int
+ file_descriptor_source_impl::read_items(char *buf, int nitems)
+ {
+ assert(nitems > 0);
+ assert(d_residue_len < d_itemsize);
+
+ int nbytes_read = 0;
+
+ if(d_residue_len > 0) {
+ memcpy(buf, d_residue, d_residue_len);
+ nbytes_read = d_residue_len;
+ d_residue_len = 0;
+ }
+
+ int r = read(d_fd, buf + nbytes_read,
+ nitems * d_itemsize - nbytes_read);
+ if(r <= 0) {
+ handle_residue(buf, nbytes_read);
+ return r;
+ }
+
+ r = handle_residue(buf, r + nbytes_read);
+
+ if(r == 0) // block until we get something
+ return read_items(buf, nitems);
+
+ return r;
+ }
+
+ int
+ file_descriptor_source_impl::handle_residue(char *buf, int nbytes_read)
+ {
+ assert(nbytes_read >= 0);
+ int nitems_read = nbytes_read / d_itemsize;
+ d_residue_len = nbytes_read % d_itemsize;
+ if(d_residue_len > 0) {
+ // fprintf (stderr, "handle_residue: %d\n", d_residue_len);
+ memcpy(d_residue, buf + nbytes_read - d_residue_len, d_residue_len);
+ }
+ return nitems_read;
+ }
+
+ int
+ file_descriptor_source_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ assert(noutput_items > 0);
+
+ char *o = (char*)output_items[0];
+ int nread = 0;
+
+ while(1) {
+ int r = read_items(o, noutput_items - nread);
+ if(r == -1) {
+ if(errno == EINTR)
+ continue;
+ else {
+ perror("file_descriptor_source[read]");
+ return -1;
+ }
+ }
+ else if(r == 0) { // end of file
+ if(!d_repeat)
+ break;
+ else {
+ flush_residue();
+ if(lseek(d_fd, 0, SEEK_SET) == -1) {
+ perror("file_descriptor_source[lseek]");
+ return -1;
+ }
+ }
+ }
+ else {
+ o += r * d_itemsize;
+ nread += r;
+ break;
+ }
+ }
+
+ if(nread == 0) // EOF
+ return -1;
+
+ return nread;
+ }
+
+ } /* namespace blocks */
+} /* namespace gr */
diff --git a/gr-blocks/lib/file_descriptor_source_impl.h b/gr-blocks/lib/file_descriptor_source_impl.h
new file mode 100644
index 0000000000..dd86e18af1
--- /dev/null
+++ b/gr-blocks/lib/file_descriptor_source_impl.h
@@ -0,0 +1,58 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GR_FILE_DESCRIPTOR_SOURCE_IMPL_H
+#define INCLUDED_GR_FILE_DESCRIPTOR_SOURCE_IMPL_H
+
+#include <blocks/file_descriptor_source.h>
+
+namespace gr {
+ namespace blocks {
+
+ class file_descriptor_source_impl : public file_descriptor_source
+ {
+ private:
+ size_t d_itemsize;
+ int d_fd;
+ bool d_repeat;
+
+ unsigned char *d_residue;
+ unsigned long d_residue_len;
+
+ protected:
+ int read_items(char *buf, int nitems);
+ int handle_residue(char *buf, int nbytes_read);
+ void flush_residue() { d_residue_len = 0; }
+
+ public:
+ file_descriptor_source_impl(size_t itemsize, int fd, bool repeat);
+ ~file_descriptor_source_impl();
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace blocks */
+} /* namespace gr */
+
+#endif /* INCLUDED_GR_FILE_DESCRIPTOR_SOURCE_IMPL_H */
diff --git a/gr-blocks/lib/file_sink_base.cc b/gr-blocks/lib/file_sink_base.cc
new file mode 100644
index 0000000000..47c8f9882b
--- /dev/null
+++ b/gr-blocks/lib/file_sink_base.cc
@@ -0,0 +1,131 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2006,2007,2009,2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <blocks/file_sink_base.h>
+#include <cstdio>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdexcept>
+#include <stdio.h>
+#include <gruel/thread.h>
+
+// win32 (mingw/msvc) specific
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
+#ifdef O_BINARY
+#define OUR_O_BINARY O_BINARY
+#else
+#define OUR_O_BINARY 0
+#endif
+
+// should be handled via configure
+#ifdef O_LARGEFILE
+#define OUR_O_LARGEFILE O_LARGEFILE
+#else
+#define OUR_O_LARGEFILE 0
+#endif
+
+namespace gr {
+ namespace blocks {
+
+ file_sink_base::file_sink_base(const char *filename, bool is_binary)
+ : d_fp(0), d_new_fp(0), d_updated(false), d_is_binary(is_binary)
+ {
+ if (!open(filename))
+ throw std::runtime_error ("can't open file");
+ }
+
+ file_sink_base::~file_sink_base()
+ {
+ close();
+ if(d_fp) {
+ fclose(d_fp);
+ d_fp = 0;
+ }
+ }
+
+ bool
+ file_sink_base::open(const char *filename)
+ {
+ gruel::scoped_lock guard(d_mutex); // hold mutex for duration of this function
+
+ // we use the open system call to get access to the O_LARGEFILE flag.
+ int fd;
+ if((fd = ::open(filename,
+ O_WRONLY|O_CREAT|O_TRUNC|OUR_O_LARGEFILE|OUR_O_BINARY,
+ 0664)) < 0){
+ perror(filename);
+ return false;
+ }
+ if(d_new_fp) { // if we've already got a new one open, close it
+ fclose(d_new_fp);
+ d_new_fp = 0;
+ }
+
+ if((d_new_fp = fdopen (fd, d_is_binary ? "wb" : "w")) == NULL) {
+ perror (filename);
+ ::close(fd); // don't leak file descriptor if fdopen fails.
+ }
+
+ d_updated = true;
+ return d_new_fp != 0;
+ }
+
+ void
+ file_sink_base::close()
+ {
+ gruel::scoped_lock guard(d_mutex); // hold mutex for duration of this function
+
+ if(d_new_fp) {
+ fclose(d_new_fp);
+ d_new_fp = 0;
+ }
+ d_updated = true;
+ }
+
+ void
+ file_sink_base::do_update()
+ {
+ if(d_updated) {
+ gruel::scoped_lock guard(d_mutex); // hold mutex for duration of this block
+ if(d_fp)
+ fclose(d_fp);
+ d_fp = d_new_fp; // install new file pointer
+ d_new_fp = 0;
+ d_updated = false;
+ }
+ }
+
+ void
+ file_sink_base::set_unbuffered(bool unbuffered)
+ {
+ d_unbuffered = unbuffered;
+ }
+
+ } /* namespace blocks */
+} /* namespace gr */
diff --git a/gr-blocks/lib/file_sink_impl.cc b/gr-blocks/lib/file_sink_impl.cc
new file mode 100644
index 0000000000..88dcb5a021
--- /dev/null
+++ b/gr-blocks/lib/file_sink_impl.cc
@@ -0,0 +1,90 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2006,2007,2010,2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "file_sink_impl.h"
+#include <gr_io_signature.h>
+#include <stdexcept>
+
+namespace gr {
+ namespace blocks {
+
+ file_sink::sptr
+ file_sink::make(size_t itemsize, const char *filename)
+ {
+ return gnuradio::get_initial_sptr
+ (new file_sink_impl(itemsize, filename));
+ }
+
+ file_sink_impl::file_sink_impl(size_t itemsize, const char *filename)
+ : gr_sync_block("file_sink",
+ gr_make_io_signature(1, 1, itemsize),
+ gr_make_io_signature(0, 0, 0)),
+ file_sink_base(filename, true),
+ d_itemsize(itemsize)
+ {
+ }
+
+ file_sink_impl::~file_sink_impl()
+ {
+ }
+
+ int
+ file_sink_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ char *inbuf = (char*)input_items[0];
+ int nwritten = 0;
+
+ do_update(); // update d_fp is reqd
+
+ if(!d_fp)
+ return noutput_items; // drop output on the floor
+
+ while(nwritten < noutput_items) {
+ int count = fwrite(inbuf, d_itemsize, noutput_items - nwritten, d_fp);
+ if(count == 0) {
+ if(ferror(d_fp)) {
+ std::stringstream s;
+ s << "file_sink write failed with error " << fileno(d_fp) << std::endl;
+ throw std::runtime_error(s.str());
+ }
+ else { // is EOF
+ break;
+ }
+ }
+ nwritten += count;
+ inbuf += count * d_itemsize;
+ }
+
+ if(d_unbuffered)
+ fflush (d_fp);
+
+ return nwritten;
+ }
+
+ } /* namespace blocks */
+} /* namespace gr */
diff --git a/gr-blocks/lib/file_sink_impl.h b/gr-blocks/lib/file_sink_impl.h
new file mode 100644
index 0000000000..8e802ad88a
--- /dev/null
+++ b/gr-blocks/lib/file_sink_impl.h
@@ -0,0 +1,48 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2007,2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GR_FILE_SINK_IMPL_H
+#define INCLUDED_GR_FILE_SINK_IMPL_H
+
+#include <blocks/file_sink.h>
+
+namespace gr {
+ namespace blocks {
+
+ class file_sink_impl : public file_sink
+ {
+ private:
+ size_t d_itemsize;
+
+ public:
+ file_sink_impl(size_t itemsize, const char *filename);
+ ~file_sink_impl();
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace blocks */
+} /* namespace gr */
+
+#endif /* INCLUDED_GR_FILE_SINK_IMPL_H */
diff --git a/gr-blocks/python/qa_file_source_sink.py b/gr-blocks/python/qa_file_source_sink.py
new file mode 100644
index 0000000000..d1d67074d5
--- /dev/null
+++ b/gr-blocks/python/qa_file_source_sink.py
@@ -0,0 +1,93 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+import blocks_swig as blocks
+import os
+
+class test_file_source_sink(gr_unittest.TestCase):
+
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+ def tearDown (self):
+ self.tb = None
+
+ def test_001(self):
+ src_data = range(1000)
+ expected_result = range(1000)
+
+ filename = "tmp.32f"
+ src = gr.vector_source_f(src_data)
+ snk = blocks.file_sink(gr.sizeof_float, filename)
+ snk.set_unbuffered(True)
+
+ src2 = blocks.file_source(gr.sizeof_float, filename)
+ snk2 = gr.vector_sink_f()
+
+ self.tb.connect(src, snk)
+ self.tb.run()
+
+ self.tb.disconnect(src, snk)
+ self.tb.connect(src2, snk2)
+ self.tb.run()
+
+ os.remove(filename)
+
+ result_data = snk2.data()
+ self.assertFloatTuplesAlmostEqual(expected_result, result_data)
+
+ def test_descriptor_001(self):
+ src_data = range(1000)
+ expected_result = range(1000)
+
+ filename = "tmp.32f"
+ fhandle0 = open(filename, "wb")
+ fd0 = fhandle0.fileno()
+
+ src = gr.vector_source_f(src_data)
+ snk = blocks.file_descriptor_sink(gr.sizeof_float, fd0)
+
+ self.tb.connect(src, snk)
+ self.tb.run()
+ os.fsync(fd0)
+ fhandle0.close()
+
+ fhandle1 = open(filename, "rb")
+ fd1 = fhandle1.fileno()
+ src2 = blocks.file_descriptor_source(gr.sizeof_float, fd1, False)
+ snk2 = gr.vector_sink_f()
+
+ self.tb.disconnect(src, snk)
+ self.tb.connect(src2, snk2)
+ self.tb.run()
+ os.fsync(fd1)
+ fhandle1.close()
+
+ os.remove(filename)
+
+ result_data = snk2.data()
+ self.assertFloatTuplesAlmostEqual(expected_result, result_data)
+
+if __name__ == '__main__':
+ gr_unittest.run(test_file_source_sink, "test_file_source_sink.xml")
+
diff --git a/gr-blocks/swig/blocks_swig.i b/gr-blocks/swig/blocks_swig.i
index 974ee1e4bf..91938f3f2b 100644
--- a/gr-blocks/swig/blocks_swig.i
+++ b/gr-blocks/swig/blocks_swig.i
@@ -71,6 +71,10 @@
#include "blocks/divide_ss.h"
#include "blocks/divide_ii.h"
#include "blocks/divide_cc.h"
+#include "blocks/file_descriptor_sink.h"
+#include "blocks/file_descriptor_source.h"
+#include "blocks/file_sink_base.h"
+#include "blocks/file_sink.h"
#include "blocks/file_source.h"
#include "blocks/file_meta_sink.h"
#include "blocks/file_meta_source.h"
@@ -224,6 +228,10 @@
%include "blocks/control_loop.h"
%include "blocks/deinterleave.h"
%include "blocks/delay.h"
+%include "blocks/file_descriptor_sink.h"
+%include "blocks/file_descriptor_source.h"
+%include "blocks/file_sink_base.h"
+%include "blocks/file_sink.h"
%include "blocks/file_source.h"
%include "blocks/file_meta_sink.h"
%include "blocks/file_meta_source.h"
@@ -383,6 +391,9 @@ GR_SWIG_BLOCK_MAGIC2(blocks, divide_ff);
GR_SWIG_BLOCK_MAGIC2(blocks, divide_ss);
GR_SWIG_BLOCK_MAGIC2(blocks, divide_ii);
GR_SWIG_BLOCK_MAGIC2(blocks, divide_cc);
+GR_SWIG_BLOCK_MAGIC2(blocks, file_descriptor_sink);
+GR_SWIG_BLOCK_MAGIC2(blocks, file_descriptor_source);
+GR_SWIG_BLOCK_MAGIC2(blocks, file_sink);
GR_SWIG_BLOCK_MAGIC2(blocks, file_source);
GR_SWIG_BLOCK_MAGIC2(blocks, file_meta_sink);
GR_SWIG_BLOCK_MAGIC2(blocks, file_meta_source);