Merged origin/flow-control-100 into dev, fixed conflicts
diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt
index 4665e89..2b94539 100644
--- a/grc/CMakeLists.txt
+++ b/grc/CMakeLists.txt
@@ -24,6 +24,5 @@
 add_subdirectory(flow_control)
 add_subdirectory(misc_utils)
 install(FILES
-    gsm_block_tree.xml
-    DESTINATION share/gnuradio/grc/blocks
+    gsm_block_tree.xml DESTINATION share/gnuradio/grc/blocks
 )
diff --git a/grc/gsm_block_tree.xml b/grc/gsm_block_tree.xml
index a76547a..b482acf 100644
--- a/grc/gsm_block_tree.xml
+++ b/grc/gsm_block_tree.xml
@@ -47,10 +47,8 @@
     <cat>
       <name>Utilities</name>
       <block>gsm_bursts_printer</block>
-      <block>gsm_burst_sink</block>
-      <block>gsm_burst_source</block>
-      <block>gsm_burst_sink_qa</block>
-      <block>gsm_burst_source_qa</block>
+      <block>gsm_burst_file_sink</block>
+      <block>gsm_burst_file_source</block>
       <block>gsm_extract_system_info</block>
       <block>gsm_extract_immediate_assignment</block>
       <block>gsm_controlled_rotator_cc</block>
diff --git a/grc/misc_utils/CMakeLists.txt b/grc/misc_utils/CMakeLists.txt
index 5a3f874..bbb4bce 100644
--- a/grc/misc_utils/CMakeLists.txt
+++ b/grc/misc_utils/CMakeLists.txt
@@ -26,8 +26,6 @@
     gsm_bursts_printer.xml
     gsm_clock_offset_corrector.xml
     gsm_tmsi_dumper.xml
-    gsm_burst_sink.xml
-    gsm_burst_source.xml
-    gsm_burst_source_qa.xml
-    gsm_burst_sink_qa.xml DESTINATION share/gnuradio/grc/blocks
+    gsm_burst_file_sink.xml
+    gsm_burst_file_source.xml DESTINATION share/gnuradio/grc/blocks
 )
diff --git a/grc/misc_utils/gsm_burst_sink.xml b/grc/misc_utils/gsm_burst_file_sink.xml
similarity index 70%
rename from grc/misc_utils/gsm_burst_sink.xml
rename to grc/misc_utils/gsm_burst_file_sink.xml
index a0e7532..e468e5f 100644
--- a/grc/misc_utils/gsm_burst_sink.xml
+++ b/grc/misc_utils/gsm_burst_file_sink.xml
@@ -1,9 +1,9 @@
 <?xml version="1.0"?>
 <block>
-  <name>Burst sink</name>
-  <key>gsm_burst_sink</key>
+  <name>Burst file sink</name>
+  <key>gsm_burst_file_sink</key>
   <import>import grgsm</import>
-  <make>grgsm.burst_sink($filename)</make>
+  <make>grgsm.burst_file_sink($filename)</make>
 
   <param>
     <name>Destination file</name>
diff --git a/grc/misc_utils/gsm_burst_source.xml b/grc/misc_utils/gsm_burst_file_source.xml
similarity index 69%
rename from grc/misc_utils/gsm_burst_source.xml
rename to grc/misc_utils/gsm_burst_file_source.xml
index 9e78069..e32a708 100644
--- a/grc/misc_utils/gsm_burst_source.xml
+++ b/grc/misc_utils/gsm_burst_file_source.xml
@@ -1,9 +1,9 @@
 <?xml version="1.0"?>
 <block>
-  <name>Burst source</name>
-  <key>gsm_burst_source</key>
+  <name>Burst file source</name>
+  <key>gsm_burst_file_source</key>
   <import>import grgsm</import>
-  <make>grgsm.burst_source($filename)</make>
+  <make>grgsm.burst_file_source($filename)</make>
 
   <param>
     <name>Source file</name>
diff --git a/grc/misc_utils/gsm_burst_sink_qa.xml b/grc/misc_utils/gsm_burst_sink_qa.xml
deleted file mode 100644
index c028da3..0000000
--- a/grc/misc_utils/gsm_burst_sink_qa.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<block>
-  <name>QA Burst sink</name>
-  <key>gsm_burst_sink_qa</key>
-  <import>import grgsm</import>
-  <make>grgsm.burst_sink_qa()</make>
-
-  <sink>
-    <name>in</name>
-    <type>message</type>
-  </sink>
-</block>
diff --git a/grc/misc_utils/gsm_bursts_printer.xml b/grc/misc_utils/gsm_bursts_printer.xml
index abdb532..821e6bb 100644
--- a/grc/misc_utils/gsm_bursts_printer.xml
+++ b/grc/misc_utils/gsm_bursts_printer.xml
@@ -4,7 +4,8 @@
   <key>gsm_bursts_printer</key>
   <import>import grgsm</import>
   <import>import pmt</import>
-  <make>grgsm.bursts_printer(pmt.intern($prepend_string), $prepend_fnr, $prepend_frame_count, $print_payload_only)</make>
+  <make>grgsm.bursts_printer(pmt.intern($prepend_string), $prepend_fnr,
+    $prepend_frame_count, $print_payload_only, $ignore_dummy_bursts)</make>
 
   <param>
     <name>Prepend String</name>
@@ -55,6 +56,20 @@
       <key>True</key>
     </option>
   </param>
+  <param>
+    <name>Ignore dummy bursts</name>
+    <key>ignore_dummy_bursts</key>
+    <value>False</value>
+    <type>bool</type>
+    <option>
+      <name>False</name>
+      <key>False</key>
+    </option>
+    <option>
+      <name>True</name>
+      <key>True</key>
+    </option>
+  </param>
 
   <sink>
     <name>bursts</name>
@@ -70,6 +85,8 @@
 
 If "Print payload only" is enabled, then only the two data blocks of a burst are printed, tail bits, stealing bits and training sequence are omitted.
 
-Enabling all three options results in an output that is similar to the output of airprobe, i.e. the format is "frame_nr frame_count: databits"
+If "Ignore dummy bursts" is enabled, then the burst printer will not print dummy bursts (see GSM 05.02)
+
+Enabling first three options (or all four options) results in an output that is similar to the output of airprobe, i.e. the format is "frame_nr frame_count: databits"
   </doc>
 </block>
diff --git a/grc/misc_utils/gsm_message_printer.xml b/grc/misc_utils/gsm_message_printer.xml
index 8b44b22..7e390ed 100644
--- a/grc/misc_utils/gsm_message_printer.xml
+++ b/grc/misc_utils/gsm_message_printer.xml
@@ -4,7 +4,7 @@
   <key>gsm_message_printer</key>
   <import>import grgsm</import>
   <import>import pmt</import>
-  <make>grgsm.message_printer(pmt.intern($prepend_string))</make>
+  <make>grgsm.message_printer(pmt.intern($prepend_string), $print_gsmtap_header)</make>
 
   <param>
     <name>Prepend String</name>
@@ -13,6 +13,20 @@
     <type>string</type>
     <hide>part</hide>
   </param>
+  <param>
+    <name>Print GSMTap header</name>
+    <key>print_gsmtap_header</key>
+    <value>False</value>
+    <type>bool</type>
+    <option>
+      <name>False</name>
+      <key>False</key>
+    </option>
+    <option>
+      <name>True</name>
+      <key>True</key>
+    </option>
+  </param>
 
   <sink>
     <name>msgs</name>
diff --git a/grc/qa_utils/CMakeLists.txt b/grc/qa_utils/CMakeLists.txt
new file mode 100644
index 0000000..1f57aa1
--- /dev/null
+++ b/grc/qa_utils/CMakeLists.txt
@@ -0,0 +1,25 @@
+# Copyright 2011,2012 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.
+
+install(FILES
+    gsm_burst_source.xml
+    gsm_burst_sink.xml
+    gsm_message_source.xml
+    gsm_message_sink.xml DESTINATION share/gnuradio/grc/blocks
+)
diff --git a/grc/qa_utils/gsm_burst_sink.xml b/grc/qa_utils/gsm_burst_sink.xml
new file mode 100644
index 0000000..740960f
--- /dev/null
+++ b/grc/qa_utils/gsm_burst_sink.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<block>
+  <name>Burst sink</name>
+  <key>gsm_burst_sink</key>
+  <import>import grgsm</import>
+  <make>grgsm.burst_sink()</make>
+
+  <sink>
+    <name>in</name>
+    <type>message</type>
+  </sink>
+</block>
diff --git a/grc/misc_utils/gsm_burst_source_qa.xml b/grc/qa_utils/gsm_burst_source.xml
similarity index 79%
rename from grc/misc_utils/gsm_burst_source_qa.xml
rename to grc/qa_utils/gsm_burst_source.xml
index bb04cca..9f55ac5 100644
--- a/grc/misc_utils/gsm_burst_source_qa.xml
+++ b/grc/qa_utils/gsm_burst_source.xml
@@ -1,9 +1,9 @@
 <?xml version="1.0"?>
 <block>
-  <name>QA Burst source</name>
-  <key>gsm_burst_source_qa</key>
+  <name>Burst source</name>
+  <key>gsm_burst_source</key>
   <import>import grgsm</import>
-  <make>grgsm.burst_source_qa($framenumbers, $timeslots, $bursts)</make>
+  <make>grgsm.burst_source($framenumbers, $timeslots, $bursts)</make>
 
   <param>
     <name>Frame numbers</name>
diff --git a/grc/qa_utils/gsm_message_sink.xml b/grc/qa_utils/gsm_message_sink.xml
new file mode 100644
index 0000000..e0d6ac0
--- /dev/null
+++ b/grc/qa_utils/gsm_message_sink.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<block>
+  <name>Message Sink</name>
+  <key>gsm_message_sink</key>
+  <import>import grgsm</import>
+  <make>grgsm.message_sink()</make>
+
+  <sink>
+    <name>in</name>
+    <type>message</type>
+  </sink>
+  
+  <doc>
+This block is a message sink for testing purposes.
+
+The data can be retrieved using function get_messages()
+
+  </doc>
+</block>
diff --git a/grc/qa_utils/gsm_message_source.xml b/grc/qa_utils/gsm_message_source.xml
new file mode 100644
index 0000000..ab06f65
--- /dev/null
+++ b/grc/qa_utils/gsm_message_source.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<block>
+  <name>Message Source</name>
+  <key>gsm_message_source</key>
+  <import>import grgsm</import>
+  <make>grgsm.message_source($messages)</make>
+
+  <param>
+    <name>Messages</name>
+    <key>messages</key>
+    <value>["02 04 01 00 00 00 c9 00 00 1d 3c e5 02 00 01 00 15 06 21 00 01 f0 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b",
+"02 04 01 00 00 00 ca 00 00 1d 3c e9 02 00 02 00 15 06 21 00 01 f0 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b",
+"02 04 01 00 00 00 cb 00 00 1d 3d 0e 01 00 00 00 59 06 1a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff e5 04 00",
+"02 04 01 00 00 00 cb 00 00 1d 3d 12 02 00 00 00 15 06 21 00 01 f0 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b"]</value>
+    <type>raw</type>
+    <hide>true</hide>
+  </param>
+
+  <source>
+    <name>msgs</name>
+    <type>message</type>
+  </source>
+
+  <doc>
+This block is a basic message source for testing purposes.
+
+It takes a list of strings as input, where each string
+is a whitespace-separated list of hexadecimal values representing the data bytes of a message including the gsmtap header.
+
+Such strings can be obtained using the message printer with option "Print GSMTap header"
+  </doc>
+</block>
diff --git a/include/grgsm/CMakeLists.txt b/include/grgsm/CMakeLists.txt
index 385572a..e9f6cc2 100644
--- a/include/grgsm/CMakeLists.txt
+++ b/include/grgsm/CMakeLists.txt
@@ -32,4 +32,5 @@
 add_subdirectory(demapping)
 add_subdirectory(receiver)
 add_subdirectory(misc_utils)
+add_subdirectory(qa_utils)
 add_subdirectory(flow_control)
diff --git a/include/grgsm/misc_utils/CMakeLists.txt b/include/grgsm/misc_utils/CMakeLists.txt
index 8b74fc7..527ae51 100644
--- a/include/grgsm/misc_utils/CMakeLists.txt
+++ b/include/grgsm/misc_utils/CMakeLists.txt
@@ -22,14 +22,12 @@
 ########################################################################
 install(FILES
     bursts_printer.h
-    burst_sink.h
-    burst_source.h
-    burst_sink_qa.h
-    burst_source_qa.h
+    burst_file_source.h
+    burst_file_sink.h
     extract_system_info.h
     extract_immediate_assignment.h
     controlled_rotator_cc.h
     controlled_const_source_f.h
-    message_printer.h 
+    message_printer.h
     tmsi_dumper.h DESTINATION include/grgsm/misc_utils
 )
diff --git a/include/grgsm/misc_utils/burst_sink.h b/include/grgsm/misc_utils/burst_file_sink.h
similarity index 75%
copy from include/grgsm/misc_utils/burst_sink.h
copy to include/grgsm/misc_utils/burst_file_sink.h
index 6903df9..7263baa 100644
--- a/include/grgsm/misc_utils/burst_sink.h
+++ b/include/grgsm/misc_utils/burst_file_sink.h
@@ -20,8 +20,8 @@
  *
  */
 
-#ifndef INCLUDED_GSM_BURST_SINK_H
-#define INCLUDED_GSM_BURST_SINK_H
+#ifndef INCLUDED_GSM_BURST_FILE_SINK_H
+#define INCLUDED_GSM_BURST_FILE_SINK_H
 
 #include <grgsm/api.h>
 #include <gnuradio/block.h>
@@ -34,17 +34,17 @@
      * \ingroup gsm
      *
      */
-    class GSM_API burst_sink : virtual public gr::block
+    class GSM_API burst_file_sink : virtual public gr::block
     {
      public:
-      typedef boost::shared_ptr<burst_sink> sptr;
+      typedef boost::shared_ptr<burst_file_sink> sptr;
 
       /*!
-       * \brief Return a shared_ptr to a new instance of grgsm::burst_sink.
+       * \brief Return a shared_ptr to a new instance of grgsm::burst_file_sink.
        *
-       * To avoid accidental use of raw pointers, grgsm::burst_sink's
+       * To avoid accidental use of raw pointers, grgsm::burst_file_sink's
        * constructor is in a private implementation
-       * class. grgsm::burst_sink::make is the public interface for
+       * class. grgsm::burst_file_sink::make is the public interface for
        * creating new instances.
        */
       static sptr make(const std::string &filename);
@@ -52,5 +52,5 @@
   } // namespace gsm
 } // namespace gr
 
-#endif /* INCLUDED_GSM_BURST_SINK_H */
+#endif /* INCLUDED_GSM_BURST_FILE_SINK_H */
 
diff --git a/include/grgsm/misc_utils/burst_source.h b/include/grgsm/misc_utils/burst_file_source.h
similarity index 75%
rename from include/grgsm/misc_utils/burst_source.h
rename to include/grgsm/misc_utils/burst_file_source.h
index bd8644f..e18ef44 100644
--- a/include/grgsm/misc_utils/burst_source.h
+++ b/include/grgsm/misc_utils/burst_file_source.h
@@ -20,8 +20,8 @@
  *
  */
 
-#ifndef INCLUDED_GSM_BURST_SOURCE_H
-#define INCLUDED_GSM_BURST_SOURCE_H
+#ifndef INCLUDED_GSM_BURST_FILE_SOURCE_H
+#define INCLUDED_GSM_BURST_FILE_SOURCE_H
 
 #include <grgsm/api.h>
 #include <gnuradio/block.h>
@@ -34,17 +34,17 @@
      * \ingroup gsm
      *
      */
-    class GSM_API burst_source : virtual public gr::block
+    class GSM_API burst_file_source : virtual public gr::block
     {
      public:
-      typedef boost::shared_ptr<burst_source> sptr;
+      typedef boost::shared_ptr<burst_file_source> sptr;
 
       /*!
-       * \brief Return a shared_ptr to a new instance of grgsm::burst_source.
+       * \brief Return a shared_ptr to a new instance of grgsm::burst_file_source.
        *
-       * To avoid accidental use of raw pointers, grgsm::burst_source's
+       * To avoid accidental use of raw pointers, grgsm::burst_file_source's
        * constructor is in a private implementation
-       * class. grgsm::burst_source::make is the public interface for
+       * class. grgsm::burst_file_source::make is the public interface for
        * creating new instances.
        */
       static sptr make(const std::string &filename);
@@ -53,5 +53,5 @@
   } // namespace gsm
 } // namespace gr
 
-#endif /* INCLUDED_GSM_BURST_SOURCE_H */
+#endif /* INCLUDED_GSM_BURST_FILE_SOURCE_H */
 
diff --git a/include/grgsm/misc_utils/burst_sink_qa.h b/include/grgsm/misc_utils/burst_sink_qa.h
deleted file mode 100644
index 3b5cac2..0000000
--- a/include/grgsm/misc_utils/burst_sink_qa.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* -*- c++ -*- */
-/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
- * @section LICENSE
- *
- * Gr-gsm 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.
- *
- * Gr-gsm 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 gr-gsm; see the file COPYING.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef INCLUDED_GSM_BURST_SINK_QA_H
-#define INCLUDED_GSM_BURST_SINK_QA_H
-
-#include <grgsm/api.h>
-#include <gnuradio/block.h>
-
-namespace gr {
-  namespace gsm {
-
-    /*!
-     * \brief <+description of block+>
-     * \ingroup gsm
-     *
-     */
-    class GSM_API burst_sink_qa : virtual public gr::block
-    {
-     public:
-      typedef boost::shared_ptr<burst_sink_qa> sptr;
-
-      /*!
-       * \brief Return a shared_ptr to a new instance of grgsm::burst_sink_qa.
-       *
-       * To avoid accidental use of raw pointers, grgsm::burst_sink_qa's
-       * constructor is in a private implementation
-       * class. grgsm::burst_sink_qa::make is the public interface for
-       * creating new instances.
-       */
-      static sptr make();
-
-      virtual std::vector<int> get_framenumbers() = 0;
-      virtual std::vector<int> get_timeslots() = 0;
-      virtual std::vector<std::string> get_burst_data() = 0;
-    };
-  } // namespace gsm
-} // namespace gr
-
-#endif /* INCLUDED_GSM_BURST_SINK_QA_H */
-
diff --git a/include/grgsm/misc_utils/bursts_printer.h b/include/grgsm/misc_utils/bursts_printer.h
index 099bf08..eb006c5 100644
--- a/include/grgsm/misc_utils/bursts_printer.h
+++ b/include/grgsm/misc_utils/bursts_printer.h
@@ -51,7 +51,8 @@
        * creating new instances.
        */
       static sptr make(pmt::pmt_t prepend_string, bool prepend_fnr=false,
-        bool prepend_frame_count=false, bool print_payload_only=false);
+        bool prepend_frame_count=false, bool print_payload_only=false,
+        bool ignore_dummy_bursts=false);
     };
 
   } // namespace gsm
diff --git a/include/grgsm/misc_utils/message_printer.h b/include/grgsm/misc_utils/message_printer.h
index 3914707..d40352f 100644
--- a/include/grgsm/misc_utils/message_printer.h
+++ b/include/grgsm/misc_utils/message_printer.h
@@ -48,7 +48,7 @@
        * class. gsm::message_printer::make is the public interface for
        * creating new instances.
        */
-      static sptr make(pmt::pmt_t prepend_string);
+      static sptr make(pmt::pmt_t prepend_string, bool print_gsmtap_header=false);
     };
 
   } // namespace gsm
diff --git a/include/grgsm/qa_utils/CMakeLists.txt b/include/grgsm/qa_utils/CMakeLists.txt
new file mode 100644
index 0000000..44bbbfb
--- /dev/null
+++ b/include/grgsm/qa_utils/CMakeLists.txt
@@ -0,0 +1,28 @@
+# Copyright 2011,2012 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.
+
+########################################################################
+# Install public header files
+########################################################################
+install(FILES
+    burst_sink.h
+    burst_source.h
+    message_source.h
+    message_sink.h DESTINATION include/grgsm/qa_utils
+)
diff --git a/include/grgsm/misc_utils/burst_sink.h b/include/grgsm/qa_utils/burst_sink.h
similarity index 88%
rename from include/grgsm/misc_utils/burst_sink.h
rename to include/grgsm/qa_utils/burst_sink.h
index 6903df9..266cbc8 100644
--- a/include/grgsm/misc_utils/burst_sink.h
+++ b/include/grgsm/qa_utils/burst_sink.h
@@ -47,7 +47,11 @@
        * class. grgsm::burst_sink::make is the public interface for
        * creating new instances.
        */
-      static sptr make(const std::string &filename);
+      static sptr make();
+
+      virtual std::vector<int> get_framenumbers() = 0;
+      virtual std::vector<int> get_timeslots() = 0;
+      virtual std::vector<std::string> get_burst_data() = 0;
     };
   } // namespace gsm
 } // namespace gr
diff --git a/include/grgsm/misc_utils/burst_source_qa.h b/include/grgsm/qa_utils/burst_source.h
similarity index 82%
rename from include/grgsm/misc_utils/burst_source_qa.h
rename to include/grgsm/qa_utils/burst_source.h
index c3c5713..bfed70f 100644
--- a/include/grgsm/misc_utils/burst_source_qa.h
+++ b/include/grgsm/qa_utils/burst_source.h
@@ -20,8 +20,8 @@
  *
  */
 
-#ifndef INCLUDED_GSM_BURST_SOURCE_QA_H
-#define INCLUDED_GSM_BURST_SOURCE_QA_H
+#ifndef INCLUDED_GSM_BURST_SOURCE_H
+#define INCLUDED_GSM_BURST_SOURCE_H
 
 #include <grgsm/api.h>
 #include <gnuradio/block.h>
@@ -34,17 +34,17 @@
      * \ingroup gsm
      *
      */
-    class GSM_API burst_source_qa : virtual public gr::block
+    class GSM_API burst_source : virtual public gr::block
     {
      public:
-      typedef boost::shared_ptr<burst_source_qa> sptr;
+      typedef boost::shared_ptr<burst_source> sptr;
 
       /*!
-       * \brief Return a shared_ptr to a new instance of grgsm::burst_source_qa.
+       * \brief Return a shared_ptr to a new instance of grgsm::burst_source.
        *
-       * To avoid accidental use of raw pointers, grgsm::burst_source_qa's
+       * To avoid accidental use of raw pointers, grgsm::burst_source's
        * constructor is in a private implementation
-       * class. grgsm::burst_source_qa::make is the public interface for
+       * class. grgsm::burst_source::make is the public interface for
        * creating new instances.
        */
       static sptr make(const std::vector<int> &framenumbers,
@@ -59,6 +59,6 @@
   } // namespace gsm
 } // namespace gr
 
-#endif /* INCLUDED_GSM_BURST_SOURCE_QA_H */
+#endif /* INCLUDED_GSM_BURST_SOURCE_H */
 
 
diff --git a/include/grgsm/misc_utils/burst_source.h b/include/grgsm/qa_utils/message_sink.h
similarity index 71%
copy from include/grgsm/misc_utils/burst_source.h
copy to include/grgsm/qa_utils/message_sink.h
index bd8644f..5cfe2f7 100644
--- a/include/grgsm/misc_utils/burst_source.h
+++ b/include/grgsm/qa_utils/message_sink.h
@@ -2,26 +2,27 @@
 /* @file
  * @author Roman Khassraf <rkhassraf@gmail.com>
  * @section LICENSE
- *
+ * 
  * Gr-gsm 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.
- *
+ * 
  * Gr-gsm 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 gr-gsm; see the file COPYING.  If not, write to
  * the Free Software Foundation, Inc., 51 Franklin Street,
  * Boston, MA 02110-1301, USA.
- *
+ * 
  */
 
-#ifndef INCLUDED_GSM_BURST_SOURCE_H
-#define INCLUDED_GSM_BURST_SOURCE_H
+
+#ifndef INCLUDED_GSM_MESSAGE_SINK_H
+#define INCLUDED_GSM_MESSAGE_SINK_H
 
 #include <grgsm/api.h>
 #include <gnuradio/block.h>
@@ -34,24 +35,26 @@
      * \ingroup gsm
      *
      */
-    class GSM_API burst_source : virtual public gr::block
+    class GSM_API message_sink : virtual public gr::block
     {
      public:
-      typedef boost::shared_ptr<burst_source> sptr;
+      typedef boost::shared_ptr<message_sink> sptr;
 
       /*!
-       * \brief Return a shared_ptr to a new instance of grgsm::burst_source.
+       * \brief Return a shared_ptr to a new instance of grgsm::message_sink.
        *
-       * To avoid accidental use of raw pointers, grgsm::burst_source's
+       * To avoid accidental use of raw pointers, grgsm::message_sink's
        * constructor is in a private implementation
-       * class. grgsm::burst_source::make is the public interface for
+       * class. grgsm::message_sink::make is the public interface for
        * creating new instances.
        */
-      static sptr make(const std::string &filename);
+      static sptr make();
+      
+      virtual std::vector<std::string> get_messages() = 0;
     };
 
   } // namespace gsm
 } // namespace gr
 
-#endif /* INCLUDED_GSM_BURST_SOURCE_H */
+#endif /* INCLUDED_GSM_MESSAGE_SINK_H */
 
diff --git a/include/grgsm/misc_utils/burst_source.h b/include/grgsm/qa_utils/message_source.h
similarity index 69%
copy from include/grgsm/misc_utils/burst_source.h
copy to include/grgsm/qa_utils/message_source.h
index bd8644f..5c3e8a1 100644
--- a/include/grgsm/misc_utils/burst_source.h
+++ b/include/grgsm/qa_utils/message_source.h
@@ -20,8 +20,9 @@
  *
  */
 
-#ifndef INCLUDED_GSM_BURST_SOURCE_H
-#define INCLUDED_GSM_BURST_SOURCE_H
+
+#ifndef INCLUDED_GSM_MESSAGE_SOURCE_H
+#define INCLUDED_GSM_MESSAGE_SOURCE_H
 
 #include <grgsm/api.h>
 #include <gnuradio/block.h>
@@ -34,24 +35,26 @@
      * \ingroup gsm
      *
      */
-    class GSM_API burst_source : virtual public gr::block
+    class GSM_API message_source : virtual public gr::block
     {
      public:
-      typedef boost::shared_ptr<burst_source> sptr;
+      typedef boost::shared_ptr<message_source> sptr;
 
       /*!
-       * \brief Return a shared_ptr to a new instance of grgsm::burst_source.
+       * \brief Return a shared_ptr to a new instance of grgsm::message_source.
        *
-       * To avoid accidental use of raw pointers, grgsm::burst_source's
+       * To avoid accidental use of raw pointers, grgsm::message_source's
        * constructor is in a private implementation
-       * class. grgsm::burst_source::make is the public interface for
+       * class. grgsm::message_source::make is the public interface for
        * creating new instances.
        */
-      static sptr make(const std::string &filename);
+      static sptr make(const std::vector<std::string> &msg_data);
+
+      virtual void set_msg_data(const std::vector<std::string> &msg_data) = 0;
     };
 
   } // namespace gsm
 } // namespace gr
 
-#endif /* INCLUDED_GSM_BURST_SOURCE_H */
+#endif /* INCLUDED_GSM_MESSAGE_SOURCE_H */
 
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 05455a3..c5fca8a 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -54,11 +54,14 @@
     misc_utils/controlled_const_source_f_impl.cc
     misc_utils/message_printer_impl.cc
     misc_utils/tmsi_dumper_impl.cc
-    misc_utils/burst_sink_impl.cc
-    misc_utils/burst_source_impl.cc
-    misc_utils/burst_sink_qa_impl.cc
-    misc_utils/burst_source_qa_impl.cc
-    decryption/decryption_impl.cc )
+    misc_utils/burst_file_sink_impl.cc
+    misc_utils/burst_file_source_impl.cc
+    qa_utils/burst_sink_impl.cc
+    qa_utils/burst_source_impl.cc
+    qa_utils/message_source_impl.cc
+    qa_utils/message_sink_impl.cc
+    decryption/decryption_impl.cc
+)
 
 add_library(gnuradio-grgsm SHARED ${grgsm_sources})
 target_link_libraries(gnuradio-grgsm ${Boost_LIBRARIES} ${GNURADIO_RUNTIME_LIBRARIES} ${VOLK_LIBRARIES} ${LIBOSMOCORE_LIBRARIES}
diff --git a/lib/misc_utils/burst_sink_impl.cc b/lib/misc_utils/burst_file_sink_impl.cc
similarity index 76%
rename from lib/misc_utils/burst_sink_impl.cc
rename to lib/misc_utils/burst_file_sink_impl.cc
index fdb7d98..25a262e 100644
--- a/lib/misc_utils/burst_sink_impl.cc
+++ b/lib/misc_utils/burst_file_sink_impl.cc
@@ -25,36 +25,36 @@
 #endif
 
 #include <gnuradio/io_signature.h>
-#include "burst_sink_impl.h"
+#include "burst_file_sink_impl.h"
 #include "stdio.h"
 
 namespace gr {
   namespace gsm {
 
-    burst_sink::sptr
-    burst_sink::make(const std::string &filename)
+    burst_file_sink::sptr
+    burst_file_sink::make(const std::string &filename)
     {
       return gnuradio::get_initial_sptr
-        (new burst_sink_impl(filename));
+        (new burst_file_sink_impl(filename));
     }
 
     /*
      * The private constructor
      */
-    burst_sink_impl::burst_sink_impl(const std::string &filename)
-      : gr::block("burst_sink",
+    burst_file_sink_impl::burst_file_sink_impl(const std::string &filename)
+      : gr::block("burst_file_sink",
               gr::io_signature::make(0, 0, 0),
               gr::io_signature::make(0, 0, 0)),
               d_output_file(filename.c_str(), std::ofstream::binary)
     {
         message_port_register_in(pmt::mp("in"));
-        set_msg_handler(pmt::mp("in"), boost::bind(&burst_sink_impl::process_burst, this, _1));
+        set_msg_handler(pmt::mp("in"), boost::bind(&burst_file_sink_impl::process_burst, this, _1));
     }
 
     /*
      * Our virtual destructor.
      */
-    burst_sink_impl::~burst_sink_impl()
+    burst_file_sink_impl::~burst_file_sink_impl()
     {
         if (d_output_file.is_open())
         {
@@ -62,7 +62,7 @@
         }
     }
 
-    void burst_sink_impl::process_burst(pmt::pmt_t msg)
+    void burst_file_sink_impl::process_burst(pmt::pmt_t msg)
     {
         std::string s = pmt::serialize_str(msg);
         const char *serialized = s.data();
diff --git a/lib/misc_utils/burst_sink_impl.h b/lib/misc_utils/burst_file_sink_impl.h
similarity index 75%
rename from lib/misc_utils/burst_sink_impl.h
rename to lib/misc_utils/burst_file_sink_impl.h
index f981826..898c609 100644
--- a/lib/misc_utils/burst_sink_impl.h
+++ b/lib/misc_utils/burst_file_sink_impl.h
@@ -20,27 +20,27 @@
  *
  */
 
-#ifndef INCLUDED_GSM_BURST_SINK_IMPL_H
-#define INCLUDED_GSM_BURST_SINK_IMPL_H
+#ifndef INCLUDED_GSM_BURST_FILE_SINK_IMPL_H
+#define INCLUDED_GSM_BURST_FILE_SINK_IMPL_H
 
-#include <grgsm/misc_utils/burst_sink.h>
+#include <grgsm/misc_utils/burst_file_sink.h>
 #include <fstream>
 
 namespace gr {
   namespace gsm {
 
-    class burst_sink_impl : public burst_sink
+    class burst_file_sink_impl : public burst_file_sink
     {
      private:
         std::ofstream d_output_file;
      public:
-      burst_sink_impl(const std::string &filename);
-      ~burst_sink_impl();
+      burst_file_sink_impl(const std::string &filename);
+      ~burst_file_sink_impl();
       void process_burst(pmt::pmt_t msg);
     };
 
   } // namespace gsm
 } // namespace gr
 
-#endif /* INCLUDED_GSM_BURST_SINK_IMPL_H */
+#endif /* INCLUDED_GSM_BURST_FILE_SINK_IMPL_H */
 
diff --git a/lib/misc_utils/burst_source_impl.cc b/lib/misc_utils/burst_file_source_impl.cc
similarity index 79%
rename from lib/misc_utils/burst_source_impl.cc
rename to lib/misc_utils/burst_file_source_impl.cc
index 76d1eaa..4661dfb 100644
--- a/lib/misc_utils/burst_source_impl.cc
+++ b/lib/misc_utils/burst_file_source_impl.cc
@@ -25,7 +25,7 @@
 #endif
 
 #include <gnuradio/io_signature.h>
-#include "burst_source_impl.h"
+#include "burst_file_source_impl.h"
 #include "stdio.h"
 
 #define PMT_SIZE 174
@@ -33,18 +33,18 @@
 namespace gr {
   namespace gsm {
 
-    burst_source::sptr
-    burst_source::make(const std::string &filename)
+    burst_file_source::sptr
+    burst_file_source::make(const std::string &filename)
     {
       return gnuradio::get_initial_sptr
-        (new burst_source_impl(filename));
+        (new burst_file_source_impl(filename));
     }
 
     /*
      * The private constructor
      */
-    burst_source_impl::burst_source_impl(const std::string &filename)
-      : gr::block("burst_source",
+    burst_file_source_impl::burst_file_source_impl(const std::string &filename)
+      : gr::block("burst_file_source",
               gr::io_signature::make(0, 0, 0),
               gr::io_signature::make(0, 0, 0)),
               d_input_file(filename.c_str(), std::ifstream::binary),
@@ -56,22 +56,22 @@
     /*
      * Our virtual destructor.
      */
-    burst_source_impl::~burst_source_impl()
+    burst_file_source_impl::~burst_file_source_impl()
     {
         if (d_finished == false){
             d_finished = true;
         }
     }
 
-    bool burst_source_impl::start()
+    bool burst_file_source_impl::start()
     {
         d_finished = false;
         d_thread = boost::shared_ptr<gr::thread::thread>
-            (new gr::thread::thread(boost::bind(&burst_source_impl::run, this)));
+            (new gr::thread::thread(boost::bind(&burst_file_source_impl::run, this)));
         return block::start();
     }
 
-    bool burst_source_impl::stop()
+    bool burst_file_source_impl::stop()
     {
         d_finished = true;
         d_thread->interrupt();
@@ -79,12 +79,12 @@
         return block::stop();
     }
 
-    bool burst_source_impl::finished()
+    bool burst_file_source_impl::finished()
     {
         return d_finished;
     }
 
-    void burst_source_impl::run()
+    void burst_file_source_impl::run()
     {
         char *unserialized = (char*)malloc(sizeof(char) * PMT_SIZE);
         while (d_input_file.read(unserialized, PMT_SIZE) && !d_finished)
diff --git a/lib/misc_utils/burst_source_impl.h b/lib/misc_utils/burst_file_source_impl.h
similarity index 76%
rename from lib/misc_utils/burst_source_impl.h
rename to lib/misc_utils/burst_file_source_impl.h
index 85217b0..383dc90 100644
--- a/lib/misc_utils/burst_source_impl.h
+++ b/lib/misc_utils/burst_file_source_impl.h
@@ -20,16 +20,16 @@
  *
  */
 
-#ifndef INCLUDED_GSM_BURST_SOURCE_IMPL_H
-#define INCLUDED_GSM_BURST_SOURCE_IMPL_H
+#ifndef INCLUDED_GSM_BURST_FILE_SOURCE_IMPL_H
+#define INCLUDED_GSM_BURST_FILE_SOURCE_IMPL_H
 
-#include <grgsm/misc_utils/burst_source.h>
+#include <grgsm/misc_utils/burst_file_source.h>
 #include <fstream>
 
 namespace gr {
   namespace gsm {
 
-    class burst_source_impl : public burst_source
+    class burst_file_source_impl : public burst_file_source
     {
      private:
         boost::shared_ptr<gr::thread::thread> d_thread;
@@ -37,8 +37,8 @@
         bool d_finished;
         void run();
      public:
-        burst_source_impl(const std::string &filename);
-        ~burst_source_impl();
+        burst_file_source_impl(const std::string &filename);
+        ~burst_file_source_impl();
         bool start();
         bool stop();
         bool finished();
@@ -46,5 +46,5 @@
   } // namespace gsm
 } // namespace gr
 
-#endif /* INCLUDED_GSM_BURST_SOURCE_IMPL_H */
+#endif /* INCLUDED_GSM_BURST_FILE_SOURCE_IMPL_H */
 
diff --git a/lib/misc_utils/bursts_printer_impl.cc b/lib/misc_utils/bursts_printer_impl.cc
index 3b4f026..fd93d79 100644
--- a/lib/misc_utils/bursts_printer_impl.cc
+++ b/lib/misc_utils/bursts_printer_impl.cc
@@ -37,6 +37,19 @@
 namespace gr {
   namespace gsm {
     boost::mutex printer_mutex;
+    // dummy burst defined in gsm 05.02, section 5.2.6
+    const int8_t bursts_printer_impl::d_dummy_burst[] = {0,0,0,
+        1,1,1,1,1,0,1,1,0,1,1,1,0,1,1,0,
+        0,0,0,0,1,0,1,0,0,1,0,0,1,1,1,0,
+        0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,
+        0,0,0,1,1,1,1,1,0,0,0,1,1,1,0,0,
+        0,1,0,1,1,1,0,0,0,1,0,1,1,1,0,0,
+        0,1,0,1,0,1,1,1,0,1,0,0,1,0,1,0,
+        0,0,1,1,0,0,1,1,0,0,1,1,1,0,0,1,
+        1,1,1,0,1,0,0,1,1,1,1,1,0,0,0,1,
+        0,0,1,0,1,1,1,1,1,0,1,0,1,0,
+        0,0,0 };
+
     void bursts_printer_impl::bursts_print(pmt::pmt_t msg)
     {
         pmt::pmt_t header_plus_burst = pmt::cdr(msg);
@@ -46,6 +59,11 @@
         size_t burst_len=pmt::blob_length(header_plus_burst)-sizeof(gsmtap_hdr);
         uint32_t frame_nr = be32toh(header->frame_number);
 
+        if (d_ignore_dummy_bursts && is_dummy_burst(burst, burst_len))
+        {
+            return;
+        }
+
         std::cout << d_prepend_string;
         if (d_prepend_fnr)
         {
@@ -94,19 +112,38 @@
         std::cout << std::endl;
     }
 
+    bool bursts_printer_impl::is_dummy_burst(int8_t *burst, size_t burst_len)
+    {
+        if (burst_len != DUMMY_BURST_LEN)
+        {
+            return false;
+        }
+        for (int i=0; i<DUMMY_BURST_LEN; i++)
+        {
+            if (burst[i] != d_dummy_burst[i])
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+
     bursts_printer::sptr
     bursts_printer::make(pmt::pmt_t prepend_string, bool prepend_fnr,
-        bool prepend_frame_count, bool print_payload_only)
+        bool prepend_frame_count, bool print_payload_only,
+        bool ignore_dummy_bursts)
     {
       return gnuradio::get_initial_sptr
-        (new bursts_printer_impl(prepend_string, prepend_fnr, prepend_frame_count, print_payload_only));
+        (new bursts_printer_impl(prepend_string, prepend_fnr, prepend_frame_count,
+            print_payload_only, ignore_dummy_bursts));
     }
 
     /*
      * The private constructor
      */
     bursts_printer_impl::bursts_printer_impl(pmt::pmt_t prepend_string, bool prepend_fnr,
-        bool prepend_frame_count, bool print_payload_only)
+        bool prepend_frame_count, bool print_payload_only,
+        bool ignore_dummy_bursts)
       : gr::block("bursts_printer",
               gr::io_signature::make(0, 0, 0),
               gr::io_signature::make(0, 0, 0))
@@ -115,6 +152,8 @@
         d_prepend_fnr = prepend_fnr;
         d_prepend_frame_count = prepend_frame_count;
         d_print_payload_only = print_payload_only;
+        d_ignore_dummy_bursts = ignore_dummy_bursts;
+
         message_port_register_in(pmt::mp("bursts"));
         set_msg_handler(pmt::mp("bursts"), boost::bind(&bursts_printer_impl::bursts_print, this, _1));
     }
diff --git a/lib/misc_utils/bursts_printer_impl.h b/lib/misc_utils/bursts_printer_impl.h
index 5a8a7ed..e438c37 100644
--- a/lib/misc_utils/bursts_printer_impl.h
+++ b/lib/misc_utils/bursts_printer_impl.h
@@ -23,6 +23,8 @@
 #ifndef INCLUDED_GSM_BURSTS_PRINTER_IMPL_H
 #define INCLUDED_GSM_BURSTS_PRINTER_IMPL_H
 
+#define DUMMY_BURST_LEN 148
+
 #include <grgsm/misc_utils/bursts_printer.h>
 #include <set>
 
@@ -37,9 +39,13 @@
       bool d_prepend_fnr;
       bool d_prepend_frame_count;
       bool d_print_payload_only;
+      bool d_ignore_dummy_bursts;
+      bool is_dummy_burst(int8_t *burst, size_t burst_len);
+      static const int8_t d_dummy_burst[];
      public:
       bursts_printer_impl(pmt::pmt_t prepend_string, bool prepend_fnr=false,
-        bool prepend_frame_count=false, bool print_payload_only=false);
+        bool prepend_frame_count=false, bool print_payload_only=false,
+        bool ignore_dummy_bursts=false);
       ~bursts_printer_impl();
     };
 
diff --git a/lib/misc_utils/message_printer_impl.cc b/lib/misc_utils/message_printer_impl.cc
index d02e2fe..2599f65 100644
--- a/lib/misc_utils/message_printer_impl.cc
+++ b/lib/misc_utils/message_printer_impl.cc
@@ -41,7 +41,15 @@
         gsmtap_hdr * header = (gsmtap_hdr *)message_plus_header;
         
         std::cout << d_prepend_string;
-        for(int ii=sizeof(gsmtap_hdr); ii<message_plus_header_len; ii++)
+        
+        int start_index = sizeof(gsmtap_hdr);
+        
+        if (d_print_gsmtap_header)
+        {
+            start_index = 0;
+        }
+        
+        for(int ii=start_index; ii<message_plus_header_len; ii++)
         {
             printf(" %02x", message_plus_header[ii]);
         }
@@ -49,24 +57,24 @@
     }
 
     message_printer::sptr
-    message_printer::make(pmt::pmt_t prepend_string)
+    message_printer::make(pmt::pmt_t prepend_string, bool print_gsmtap_header)
     {
       return gnuradio::get_initial_sptr
-        (new message_printer_impl(prepend_string));
+        (new message_printer_impl(prepend_string, print_gsmtap_header));
     }
 
     /*
      * The private constructor
      */
-    message_printer_impl::message_printer_impl(pmt::pmt_t prepend_string)
+    message_printer_impl::message_printer_impl(pmt::pmt_t prepend_string, bool print_gsmtap_header)
       : gr::block("message_printer",
               gr::io_signature::make(0, 0, 0),
               gr::io_signature::make(0, 0, 0))
     {
         d_prepend_string = prepend_string;
+        d_print_gsmtap_header = print_gsmtap_header;
         message_port_register_in(pmt::mp("msgs"));
         set_msg_handler(pmt::mp("msgs"), boost::bind(&message_printer_impl::message_print, this, _1));
-
     }
 
     /*
diff --git a/lib/misc_utils/message_printer_impl.h b/lib/misc_utils/message_printer_impl.h
index e82485e..e44288b 100644
--- a/lib/misc_utils/message_printer_impl.h
+++ b/lib/misc_utils/message_printer_impl.h
@@ -33,8 +33,9 @@
      private:
       void message_print(pmt::pmt_t msg);
       pmt::pmt_t d_prepend_string;
+      bool d_print_gsmtap_header;
      public:
-      message_printer_impl(pmt::pmt_t prepend_string);
+      message_printer_impl(pmt::pmt_t prepend_string, bool print_gsmtap_header=false);
       ~message_printer_impl();
     };
 
diff --git a/lib/misc_utils/burst_sink_qa_impl.cc b/lib/qa_utils/burst_sink_impl.cc
similarity index 80%
rename from lib/misc_utils/burst_sink_qa_impl.cc
rename to lib/qa_utils/burst_sink_impl.cc
index aa9df9d..de26d39 100644
--- a/lib/misc_utils/burst_sink_qa_impl.cc
+++ b/lib/qa_utils/burst_sink_impl.cc
@@ -25,7 +25,7 @@
 #endif
 
 #include <gnuradio/io_signature.h>
-#include "burst_sink_qa_impl.h"
+#include "burst_sink_impl.h"
 #include <stdio.h>
 #include <sstream>
 #include <grgsm/gsmtap.h>
@@ -33,29 +33,29 @@
 namespace gr {
   namespace gsm {
 
-    burst_sink_qa::sptr
-    burst_sink_qa::make()
+    burst_sink::sptr
+    burst_sink::make()
     {
       return gnuradio::get_initial_sptr
-        (new burst_sink_qa_impl());
+        (new burst_sink_impl());
     }
 
     /*
      * The private constructor
      */
-    burst_sink_qa_impl::burst_sink_qa_impl()
-      : gr::block("burst_sink_qa",
+    burst_sink_impl::burst_sink_impl()
+      : gr::block("burst_sink",
               gr::io_signature::make(0, 0, 0),
               gr::io_signature::make(0, 0, 0))
     {
         message_port_register_in(pmt::mp("in"));
-        set_msg_handler(pmt::mp("in"), boost::bind(&burst_sink_qa_impl::process_burst, this, _1));
+        set_msg_handler(pmt::mp("in"), boost::bind(&burst_sink_impl::process_burst, this, _1));
     }
 
     /*
      * Our virtual destructor.
      */
-    burst_sink_qa_impl::~burst_sink_qa_impl()
+    burst_sink_impl::~burst_sink_impl()
     {
 //         for (int i=0; i<d_burst_data.size(); i++)
 //         {
@@ -63,7 +63,7 @@
 //         }
     }
 
-    void burst_sink_qa_impl::process_burst(pmt::pmt_t msg)
+    void burst_sink_impl::process_burst(pmt::pmt_t msg)
     {
         pmt::pmt_t header_plus_burst = pmt::cdr(msg);
 
@@ -90,17 +90,17 @@
         d_burst_data.push_back(burst_str.str());
     }
 
-    std::vector<int> burst_sink_qa_impl::get_framenumbers()
+    std::vector<int> burst_sink_impl::get_framenumbers()
     {
         return d_framenumbers;
     }
 
-    std::vector<int> burst_sink_qa_impl::get_timeslots()
+    std::vector<int> burst_sink_impl::get_timeslots()
     {
         return d_timeslots;
     }
 
-    std::vector<std::string> burst_sink_qa_impl::get_burst_data()
+    std::vector<std::string> burst_sink_impl::get_burst_data()
     {
         return d_burst_data;
     }
diff --git a/lib/misc_utils/burst_sink_qa_impl.h b/lib/qa_utils/burst_sink_impl.h
similarity index 81%
rename from lib/misc_utils/burst_sink_qa_impl.h
rename to lib/qa_utils/burst_sink_impl.h
index 412a0a1..42e1e4a 100644
--- a/lib/misc_utils/burst_sink_qa_impl.h
+++ b/lib/qa_utils/burst_sink_impl.h
@@ -20,24 +20,24 @@
  *
  */
 
-#ifndef INCLUDED_GSM_BURST_SINK_QA_IMPL_H
-#define INCLUDED_GSM_BURST_SINK_QA_IMPL_H
+#ifndef INCLUDED_GSM_BURST_SINK_IMPL_H
+#define INCLUDED_GSM_BURST_SINK_IMPL_H
 
-#include <grgsm/misc_utils/burst_sink_qa.h>
+#include <grgsm/qa_utils/burst_sink.h>
 #include <fstream>
 
 namespace gr {
   namespace gsm {
 
-    class burst_sink_qa_impl : public burst_sink_qa
+    class burst_sink_impl : public burst_sink
     {
      private:
       std::vector<int> d_framenumbers;
       std::vector<int> d_timeslots;
       std::vector<std::string> d_burst_data;
      public:
-      burst_sink_qa_impl();
-      ~burst_sink_qa_impl();
+      burst_sink_impl();
+      ~burst_sink_impl();
       void process_burst(pmt::pmt_t msg);
       virtual std::vector<int> get_framenumbers();
       virtual std::vector<int> get_timeslots();
@@ -47,5 +47,5 @@
   } // namespace gsm
 } // namespace gr
 
-#endif /* INCLUDED_GSM_BURST_SINK_QA_IMPL_H */
+#endif /* INCLUDED_GSM_BURST_SINK_IMPL_H */
 
diff --git a/lib/misc_utils/burst_source_qa_impl.cc b/lib/qa_utils/burst_source_impl.cc
similarity index 82%
rename from lib/misc_utils/burst_source_qa_impl.cc
rename to lib/qa_utils/burst_source_impl.cc
index 7b2d412..7391872 100644
--- a/lib/misc_utils/burst_source_qa_impl.cc
+++ b/lib/qa_utils/burst_source_impl.cc
@@ -25,7 +25,7 @@
 #endif
 
 #include <gnuradio/io_signature.h>
-#include "burst_source_qa_impl.h"
+#include "burst_source_impl.h"
 #include "stdio.h"
 #include <boost/scoped_ptr.hpp>
 #include <grgsm/gsmtap.h>
@@ -36,22 +36,22 @@
 namespace gr {
   namespace gsm {
 
-    burst_source_qa::sptr
-    burst_source_qa::make(const std::vector<int> &framenumbers,
+    burst_source::sptr
+    burst_source::make(const std::vector<int> &framenumbers,
             const std::vector<int> &timeslots,
             const std::vector<std::string> &burst_data)
     {
       return gnuradio::get_initial_sptr
-        (new burst_source_qa_impl(framenumbers, timeslots, burst_data));
+        (new burst_source_impl(framenumbers, timeslots, burst_data));
     }
 
     /*
      * The private constructor
      */
-    burst_source_qa_impl::burst_source_qa_impl(const std::vector<int> &framenumbers,
+    burst_source_impl::burst_source_impl(const std::vector<int> &framenumbers,
             const std::vector<int> &timeslots,
             const std::vector<std::string> &burst_data)
-      : gr::block("burst_source_qa",
+      : gr::block("burst_source",
               gr::io_signature::make(0, 0, 0),
               gr::io_signature::make(0, 0, 0)),
               d_finished(false)
@@ -65,37 +65,37 @@
     /*
      * Our virtual destructor.
      */
-    burst_source_qa_impl::~burst_source_qa_impl()
+    burst_source_impl::~burst_source_impl()
     {
         if (d_finished == false){
             d_finished = true;
         }
     }
 
-    void burst_source_qa_impl::set_framenumbers(const std::vector<int> &framenumbers)
+    void burst_source_impl::set_framenumbers(const std::vector<int> &framenumbers)
     {
         d_framenumbers = framenumbers;
     }
 
-    void  burst_source_qa_impl::set_timeslots(const std::vector<int> &timeslots)
+    void  burst_source_impl::set_timeslots(const std::vector<int> &timeslots)
     {
         d_timeslots = timeslots;
     }
 
-    void burst_source_qa_impl::set_burst_data(const std::vector<std::string> &burst_data)
+    void burst_source_impl::set_burst_data(const std::vector<std::string> &burst_data)
     {
         d_burst_data = burst_data;
     }
 
-    bool burst_source_qa_impl::start()
+    bool burst_source_impl::start()
     {
         d_finished = false;
         d_thread = boost::shared_ptr<gr::thread::thread>
-            (new gr::thread::thread(boost::bind(&burst_source_qa_impl::run, this)));
+            (new gr::thread::thread(boost::bind(&burst_source_impl::run, this)));
         return block::start();
     }
 
-    bool burst_source_qa_impl::stop()
+    bool burst_source_impl::stop()
     {
         d_finished = true;
         d_thread->interrupt();
@@ -103,12 +103,12 @@
         return block::stop();
     }
 
-    bool burst_source_qa_impl::finished()
+    bool burst_source_impl::finished()
     {
         return d_finished;
     }
 
-    void burst_source_qa_impl::run()
+    void burst_source_impl::run()
     {
         char *unserialized = (char*)malloc(sizeof(char) * PMT_SIZE);
 
diff --git a/lib/misc_utils/burst_source_qa_impl.h b/lib/qa_utils/burst_source_impl.h
similarity index 81%
rename from lib/misc_utils/burst_source_qa_impl.h
rename to lib/qa_utils/burst_source_impl.h
index cb62571..969faf9 100644
--- a/lib/misc_utils/burst_source_qa_impl.h
+++ b/lib/qa_utils/burst_source_impl.h
@@ -20,19 +20,19 @@
  *
  */
 
-#ifndef INCLUDED_GSM_BURST_SOURCE_QA_IMPL_H
-#define INCLUDED_GSM_BURST_SOURCE_QA_IMPL_H
+#ifndef INCLUDED_GSM_BURST_SOURCE_IMPL_H
+#define INCLUDED_GSM_BURST_SOURCE_IMPL_H
 
 #define BURST_SIZE  148
 
-#include <grgsm/misc_utils/burst_source_qa.h>
+#include <grgsm/qa_utils/burst_source.h>
 #include <fstream>
 
 
 namespace gr {
   namespace gsm {
 
-    class burst_source_qa_impl : public burst_source_qa
+    class burst_source_impl : public burst_source
     {
      private:
         boost::shared_ptr<gr::thread::thread> d_thread;
@@ -42,10 +42,10 @@
         bool d_finished;
         void run();
      public:
-        burst_source_qa_impl(const std::vector<int> &framenumbers,
+        burst_source_impl(const std::vector<int> &framenumbers,
             const std::vector<int> &timeslots,
             const std::vector<std::string> &burst_data);
-        ~burst_source_qa_impl();
+        ~burst_source_impl();
         virtual void set_framenumbers(const std::vector<int> &framenumbers);
         virtual void set_timeslots(const std::vector<int> &timeslots);
         virtual void set_burst_data(const std::vector<std::string> &burst_data);
@@ -56,6 +56,6 @@
   } // namespace gsm
 } // namespace gr
 
-#endif /* INCLUDED_GSM_BURST_SOURCE_QA_IMPL_H */
+#endif /* INCLUDED_GSM_BURST_SOURCE_IMPL_H */
 
 
diff --git a/lib/qa_utils/message_sink_impl.cc b/lib/qa_utils/message_sink_impl.cc
new file mode 100644
index 0000000..269cada
--- /dev/null
+++ b/lib/qa_utils/message_sink_impl.cc
@@ -0,0 +1,90 @@
+/* -*- c++ -*- */
+/* @file
+ * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @section LICENSE
+ *
+ * Gr-gsm 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.
+ *
+ * Gr-gsm 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 gr-gsm; 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 <gnuradio/io_signature.h>
+#include "message_sink_impl.h"
+#include <stdio.h>
+#include <sstream>
+
+namespace gr {
+  namespace gsm {
+
+    message_sink::sptr
+    message_sink::make()
+    {
+      return gnuradio::get_initial_sptr
+        (new message_sink_impl());
+    }
+
+    /*
+     * The private constructor
+     */
+    message_sink_impl::message_sink_impl()
+      : gr::block("message_sink",
+              gr::io_signature::make(0, 0, 0),
+              gr::io_signature::make(0, 0, 0))
+    {
+        message_port_register_in(pmt::mp("in"));
+        set_msg_handler(pmt::mp("in"), boost::bind(&message_sink_impl::process_message, this, _1));
+    }
+
+    /*
+     * Our virtual destructor.
+     */
+    message_sink_impl::~message_sink_impl()
+    {
+        for (int i=0; i<d_messages.size(); i++)
+        {
+            std::cout << d_messages[i].c_str() << std::endl;
+        }
+    }
+
+    void message_sink_impl::process_message(pmt::pmt_t msg)
+    {
+        pmt::pmt_t message_plus_header_blob = pmt::cdr(msg);
+        uint8_t * message_plus_header = (uint8_t *)pmt::blob_data(message_plus_header_blob);
+        size_t message_plus_header_len = pmt::blob_length(message_plus_header_blob);
+
+        std::stringstream s_msg_stream;
+        for (int i=0; i<message_plus_header_len; i++)
+        {
+            if (i>0)
+            {
+                s_msg_stream << (" ");
+            }
+            s_msg_stream << std::hex << std::setw(2) << std::setfill('0') << (unsigned)message_plus_header[i];
+        }
+        d_messages.push_back(s_msg_stream.str());
+    }
+
+    std::vector<std::string> message_sink_impl::get_messages()
+    {
+        return d_messages;
+    }
+
+  } /* namespace gsm */
+} /* namespace gr */
+
diff --git a/lib/misc_utils/burst_sink_impl.h b/lib/qa_utils/message_sink_impl.h
similarity index 68%
copy from lib/misc_utils/burst_sink_impl.h
copy to lib/qa_utils/message_sink_impl.h
index f981826..dd11819 100644
--- a/lib/misc_utils/burst_sink_impl.h
+++ b/lib/qa_utils/message_sink_impl.h
@@ -20,27 +20,28 @@
  *
  */
 
-#ifndef INCLUDED_GSM_BURST_SINK_IMPL_H
-#define INCLUDED_GSM_BURST_SINK_IMPL_H
+#ifndef INCLUDED_GSM_MESSAGE_SINK_IMPL_H
+#define INCLUDED_GSM_MESSAGE_SINK_IMPL_H
 
-#include <grgsm/misc_utils/burst_sink.h>
-#include <fstream>
+#include <grgsm/qa_utils/message_sink.h>
 
 namespace gr {
   namespace gsm {
 
-    class burst_sink_impl : public burst_sink
+    class message_sink_impl : public message_sink
     {
      private:
-        std::ofstream d_output_file;
+      std::vector<std::string> d_messages;
+
      public:
-      burst_sink_impl(const std::string &filename);
-      ~burst_sink_impl();
-      void process_burst(pmt::pmt_t msg);
+      message_sink_impl();
+      ~message_sink_impl();
+      void process_message(pmt::pmt_t msg);
+      virtual std::vector<std::string> get_messages();
     };
 
   } // namespace gsm
 } // namespace gr
 
-#endif /* INCLUDED_GSM_BURST_SINK_IMPL_H */
+#endif /* INCLUDED_GSM_MESSAGE_SINK_IMPL_H */
 
diff --git a/lib/qa_utils/message_source_impl.cc b/lib/qa_utils/message_source_impl.cc
new file mode 100644
index 0000000..2e71ba4
--- /dev/null
+++ b/lib/qa_utils/message_source_impl.cc
@@ -0,0 +1,131 @@
+/* -*- c++ -*- */
+/* @file
+ * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @section LICENSE
+ *
+ * Gr-gsm 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.
+ *
+ * Gr-gsm 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 gr-gsm; 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 <gnuradio/io_signature.h>
+#include "message_source_impl.h"
+#include <stdio.h>
+#include <grgsm/gsmtap.h>
+#include <grgsm/endian.h>
+#include <algorithm>
+#include <boost/scoped_ptr.hpp>
+#include <iostream>
+#include <string>
+#include <sstream>
+
+#define MSG_BYTE_LEN 39
+
+
+namespace gr {
+  namespace gsm {
+
+    message_source::sptr
+    message_source::make(const std::vector<std::string> &msg_data)
+    {
+      return gnuradio::get_initial_sptr
+        (new message_source_impl(msg_data));
+    }
+
+    /*
+     * The private constructor
+     */
+    message_source_impl::message_source_impl(const std::vector<std::string> &msg_data)
+      : gr::block("message_source",
+              gr::io_signature::make(0, 0, 0),
+              gr::io_signature::make(0, 0, 0)),
+              d_finished(false)
+    {
+        message_port_register_out(pmt::mp("msgs"));
+        set_msg_data(msg_data);
+    }
+
+    /*
+     * Our virtual destructor.
+     */
+    message_source_impl::~message_source_impl()
+    {
+        if (d_finished == false){
+            d_finished = true;
+        }
+    }
+
+    void message_source_impl::set_msg_data(const std::vector<std::string> &msg_data)
+    {
+        for (int i=0; i<msg_data.size(); i++)
+        {
+            std::istringstream iss(msg_data[i]);
+            std::vector<uint8_t> bytes;
+            unsigned int c;
+
+            while (iss >> std::hex >> c)
+            {
+                if (c < 256)
+                {
+                    bytes.push_back(c);
+                }
+            }
+
+            if (bytes.size() == MSG_BYTE_LEN)
+            {
+                d_msgs.push_back(bytes);
+            }
+        }
+    }
+
+    bool message_source_impl::start()
+    {
+        d_finished = false;
+        d_thread = boost::shared_ptr<gr::thread::thread>
+            (new gr::thread::thread(boost::bind(&message_source_impl::run, this)));
+        return block::start();
+    }
+
+    bool message_source_impl::stop()
+    {
+        d_finished = true;
+        d_thread->interrupt();
+        d_thread->join();
+        return block::stop();
+    }
+
+    bool message_source_impl::finished()
+    {
+        return d_finished;
+    }
+
+    void message_source_impl::run()
+    {
+        for (int i=0; i<d_msgs.size(); i++)
+        {
+            std::vector<uint8_t> current = d_msgs[i];
+            pmt::pmt_t blob_header_plus_burst = pmt::make_blob(&current[0], current.size());
+            pmt::pmt_t msg = pmt::cons(pmt::PMT_NIL, blob_header_plus_burst);
+            message_port_pub(pmt::mp("msgs"), msg);
+        }
+        post(pmt::mp("system"), pmt::cons(pmt::mp("done"), pmt::from_long(1)));
+    }
+  } /* namespace gsm */
+} /* namespace gr */
+
diff --git a/lib/misc_utils/burst_source_impl.h b/lib/qa_utils/message_source_impl.h
similarity index 64%
copy from lib/misc_utils/burst_source_impl.h
copy to lib/qa_utils/message_source_impl.h
index 85217b0..9856f78 100644
--- a/lib/misc_utils/burst_source_impl.h
+++ b/lib/qa_utils/message_source_impl.h
@@ -20,31 +20,32 @@
  *
  */
 
-#ifndef INCLUDED_GSM_BURST_SOURCE_IMPL_H
-#define INCLUDED_GSM_BURST_SOURCE_IMPL_H
+#ifndef INCLUDED_GSM_MESSAGE_SOURCE_IMPL_H
+#define INCLUDED_GSM_MESSAGE_SOURCE_IMPL_H
 
-#include <grgsm/misc_utils/burst_source.h>
-#include <fstream>
+#include <grgsm/qa_utils/message_source.h>
 
 namespace gr {
   namespace gsm {
 
-    class burst_source_impl : public burst_source
+    class message_source_impl : public message_source
     {
      private:
         boost::shared_ptr<gr::thread::thread> d_thread;
-        std::ifstream d_input_file;
+        std::vector<std::vector<uint8_t> > d_msgs;
         bool d_finished;
         void run();
      public:
-        burst_source_impl(const std::string &filename);
-        ~burst_source_impl();
-        bool start();
-        bool stop();
-        bool finished();
+      message_source_impl(const std::vector<std::string> &msg_data);
+      ~message_source_impl();
+      virtual void set_msg_data(const std::vector<std::string> &msg_data);
+      bool start();
+      bool stop();
+      bool finished();
     };
-  } // namespace gsm
+
+  } // namespace grgsm
 } // namespace gr
 
-#endif /* INCLUDED_GSM_BURST_SOURCE_IMPL_H */
+#endif /* INCLUDED_GSM_MESSAGE_SOURCE_IMPL_H */
 
diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
index da69ffd..811a3ec 100644
--- a/python/CMakeLists.txt
+++ b/python/CMakeLists.txt
@@ -47,6 +47,8 @@
 set(GR_TEST_TARGET_DEPS gr-gsm)
 set(GR_TEST_PYTHON_DIRS ${CMAKE_BINARY_DIR}/swig)
 GR_ADD_TEST(qa_decryption ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_decryption.py)
+GR_ADD_TEST(qa_burst_printer ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_burst_printer.py)
+GR_ADD_TEST(qa_message_printer ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_message_printer.py)
 GR_ADD_TEST(qa_burst_timeslot_splitter ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_burst_timeslot_splitter.py)
 GR_ADD_TEST(qa_burst_sdcch_subslot_splitter ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_burst_sdcch_subslot_splitter.py)
 GR_ADD_TEST(qa_burst_fnr_filter ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_burst_fnr_filter.py)
diff --git a/python/qa_burst_printer.py b/python/qa_burst_printer.py
new file mode 100755
index 0000000..97fbe71
--- /dev/null
+++ b/python/qa_burst_printer.py
@@ -0,0 +1,297 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# @file
+# @author Roman Khassraf <rkhassraf@gmail.com>
+# @section LICENSE
+# 
+# Gr-gsm 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.
+# 
+# Gr-gsm 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 gr-gsm; 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, blocks
+import grgsm
+import os
+import pmt
+import sys
+import tempfile
+
+class qa_burst_printer (gr_unittest.TestCase):
+   
+    def setUp (self):
+        self.tb = gr.top_block()
+        self.tmpfile = tempfile.NamedTemporaryFile()
+        self.prevfd = os.dup(sys.stdout.fileno())
+        os.dup2(self.tmpfile.fileno(), sys.stdout.fileno())
+        self.prev = sys.stdout
+        sys.stdout = os.fdopen(self.prevfd, "w")
+        
+    def tearDown (self):
+        self.tb = None
+        os.dup2(self.prevfd, self.prev.fileno())
+        sys.stdout = self.prev
+        self.tmpfile.close()
+        
+    def getOutput(self):
+        self.tmpfile.seek(0)
+        return self.tmpfile.read()
+    
+    def getOutputExpected(self, expected_lines):
+        out = ""
+        for l in expected_lines:
+            out = out + l + "\n"
+        return out
+
+    def test_001_complete_bursts_prefix (self):
+        """
+            Complete bursts, without any prefix
+        """
+        framenumbers_input = [2569043, 2569044, 2569045, 2569046]
+        timeslots_input = [2, 2, 2, 2]
+        bursts_input = [
+            "0001100000010010011110111110011111000000001010001111000000001000110101110010000011010111100101101010000001111010100010110111101011101011100000101000",
+            "0001000101111101111110000010100001011011111010111110101011101000110101110010000011010111110110111101101111110000011011010111011111001011101000011000",
+            "0000001000011110111110101011001000110000000000110110101100011000110101110010000011010111001010100101011111001000111100000100000111111000000101110000",
+            "0001101010111110010001010110101100000011101100011111110100101000110101110010000011010111111000000001010010111001111111011001000000001001000011101000"
+        ]
+        
+        expected_lines = [
+            "0001100000010010011110111110011111000000001010001111000000001000110101110010000011010111100101101010000001111010100010110111101011101011100000101000",
+            "0001000101111101111110000010100001011011111010111110101011101000110101110010000011010111110110111101101111110000011011010111011111001011101000011000",
+            "0000001000011110111110101011001000110000000000110110101100011000110101110010000011010111001010100101011111001000111100000100000111111000000101110000",
+            "0001101010111110010001010110101100000011101100011111110100101000110101110010000011010111111000000001010010111001111111011001000000001001000011101000"
+        ]
+        
+        src = grgsm.burst_source(framenumbers_input, timeslots_input, bursts_input)
+        printer = grgsm.bursts_printer(pmt.intern(""), False, False, False, False)
+        self.tb.msg_connect(src, "out", printer, "bursts")
+        self.tb.run()
+
+        self.assertEqual(self.getOutput(), self.getOutputExpected(expected_lines))
+        
+    def test_002_complete_bursts_prefix (self):
+        """
+            Complete bursts, with a string prefix
+        """
+        framenumbers_input = [2569043, 2569044, 2569045, 2569046]
+        timeslots_input = [2, 2, 2, 2]
+        bursts_input = [
+            "0001100000010010011110111110011111000000001010001111000000001000110101110010000011010111100101101010000001111010100010110111101011101011100000101000",
+            "0001000101111101111110000010100001011011111010111110101011101000110101110010000011010111110110111101101111110000011011010111011111001011101000011000",
+            "0000001000011110111110101011001000110000000000110110101100011000110101110010000011010111001010100101011111001000111100000100000111111000000101110000",
+            "0001101010111110010001010110101100000011101100011111110100101000110101110010000011010111111000000001010010111001111111011001000000001001000011101000"
+        ]
+        
+        expected_lines = [
+            "Test 0001100000010010011110111110011111000000001010001111000000001000110101110010000011010111100101101010000001111010100010110111101011101011100000101000",
+            "Test 0001000101111101111110000010100001011011111010111110101011101000110101110010000011010111110110111101101111110000011011010111011111001011101000011000",
+            "Test 0000001000011110111110101011001000110000000000110110101100011000110101110010000011010111001010100101011111001000111100000100000111111000000101110000",
+            "Test 0001101010111110010001010110101100000011101100011111110100101000110101110010000011010111111000000001010010111001111111011001000000001001000011101000"
+        ]
+        
+        src = grgsm.burst_source(framenumbers_input, timeslots_input, bursts_input)
+        printer = grgsm.bursts_printer(pmt.intern("Test "), False, False, False, False)
+        self.tb.msg_connect(src, "out", printer, "bursts")
+        self.tb.run()
+
+        self.assertEqual(self.getOutput(), self.getOutputExpected(expected_lines))
+
+    def test_003_complete_bursts_fnr (self):
+        """
+            Complete bursts, no prefix, with frame number
+        """
+        framenumbers_input = [2569043, 2569044, 2569045, 2569046]
+        timeslots_input = [2, 2, 2, 2]
+        bursts_input = [
+            "0001100000010010011110111110011111000000001010001111000000001000110101110010000011010111100101101010000001111010100010110111101011101011100000101000",
+            "0001000101111101111110000010100001011011111010111110101011101000110101110010000011010111110110111101101111110000011011010111011111001011101000011000",
+            "0000001000011110111110101011001000110000000000110110101100011000110101110010000011010111001010100101011111001000111100000100000111111000000101110000",
+            "0001101010111110010001010110101100000011101100011111110100101000110101110010000011010111111000000001010010111001111111011001000000001001000011101000"
+        ]
+        
+        expected_lines = [
+            "2569043: 0001100000010010011110111110011111000000001010001111000000001000110101110010000011010111100101101010000001111010100010110111101011101011100000101000",
+            "2569044: 0001000101111101111110000010100001011011111010111110101011101000110101110010000011010111110110111101101111110000011011010111011111001011101000011000",
+            "2569045: 0000001000011110111110101011001000110000000000110110101100011000110101110010000011010111001010100101011111001000111100000100000111111000000101110000",
+            "2569046: 0001101010111110010001010110101100000011101100011111110100101000110101110010000011010111111000000001010010111001111111011001000000001001000011101000"
+        ]
+        
+        src = grgsm.burst_source(framenumbers_input, timeslots_input, bursts_input)
+        printer = grgsm.bursts_printer(pmt.intern(""), True, False, False, False)
+        self.tb.msg_connect(src, "out", printer, "bursts")
+        self.tb.run()
+
+        self.assertEqual(self.getOutput(), self.getOutputExpected(expected_lines))
+        
+    def test_004_complete_bursts_fcount (self):
+        """
+            Complete bursts, no prefix, with frame count
+        """
+        framenumbers_input = [2569043, 2569044, 2569045, 2569046]
+        timeslots_input = [2, 2, 2, 2]
+        bursts_input = [
+            "0001100000010010011110111110011111000000001010001111000000001000110101110010000011010111100101101010000001111010100010110111101011101011100000101000",
+            "0001000101111101111110000010100001011011111010111110101011101000110101110010000011010111110110111101101111110000011011010111011111001011101000011000",
+            "0000001000011110111110101011001000110000000000110110101100011000110101110010000011010111001010100101011111001000111100000100000111111000000101110000",
+            "0001101010111110010001010110101100000011101100011111110100101000110101110010000011010111111000000001010010111001111111011001000000001001000011101000"
+        ]
+        
+        expected_lines = [
+            "3967625: 0001100000010010011110111110011111000000001010001111000000001000110101110010000011010111100101101010000001111010100010110111101011101011100000101000",
+            "3967658: 0001000101111101111110000010100001011011111010111110101011101000110101110010000011010111110110111101101111110000011011010111011111001011101000011000",
+            "3967691: 0000001000011110111110101011001000110000000000110110101100011000110101110010000011010111001010100101011111001000111100000100000111111000000101110000",
+            "3967724: 0001101010111110010001010110101100000011101100011111110100101000110101110010000011010111111000000001010010111001111111011001000000001001000011101000"
+        ]
+        
+        src = grgsm.burst_source(framenumbers_input, timeslots_input, bursts_input)
+        printer = grgsm.bursts_printer(pmt.intern(""), False, True, False, False)
+        self.tb.msg_connect(src, "out", printer, "bursts")
+        self.tb.run()
+
+        self.assertEqual(self.getOutput(), self.getOutputExpected(expected_lines))
+
+    def test_005_complete_bursts_fnr_fcount (self):
+        """
+            Complete bursts, no prefix, with frame number and frame count
+        """
+        framenumbers_input = [2569043, 2569044, 2569045, 2569046]
+        timeslots_input = [2, 2, 2, 2]
+        bursts_input = [
+            "0001100000010010011110111110011111000000001010001111000000001000110101110010000011010111100101101010000001111010100010110111101011101011100000101000",
+            "0001000101111101111110000010100001011011111010111110101011101000110101110010000011010111110110111101101111110000011011010111011111001011101000011000",
+            "0000001000011110111110101011001000110000000000110110101100011000110101110010000011010111001010100101011111001000111100000100000111111000000101110000",
+            "0001101010111110010001010110101100000011101100011111110100101000110101110010000011010111111000000001010010111001111111011001000000001001000011101000"
+        ]
+        
+        expected_lines = [
+            "2569043 3967625: 0001100000010010011110111110011111000000001010001111000000001000110101110010000011010111100101101010000001111010100010110111101011101011100000101000",
+            "2569044 3967658: 0001000101111101111110000010100001011011111010111110101011101000110101110010000011010111110110111101101111110000011011010111011111001011101000011000",
+            "2569045 3967691: 0000001000011110111110101011001000110000000000110110101100011000110101110010000011010111001010100101011111001000111100000100000111111000000101110000",
+            "2569046 3967724: 0001101010111110010001010110101100000011101100011111110100101000110101110010000011010111111000000001010010111001111111011001000000001001000011101000"
+        ]
+        
+        src = grgsm.burst_source(framenumbers_input, timeslots_input, bursts_input)
+        printer = grgsm.bursts_printer(pmt.intern(""), True, True, False, False)
+        self.tb.msg_connect(src, "out", printer, "bursts")
+        self.tb.run()
+
+        self.assertEqual(self.getOutput(), self.getOutputExpected(expected_lines))
+
+    def test_006_payload_prefix_fnr_fcount (self):
+        """
+            Payload only, no prefix, with frame number and frame count
+            Bursts 4-7 are dummy bursts
+        """
+        framenumbers_input = [2569043, 2569044, 2569045, 2569046, 1099602, 1099603, 1099604, 1099605]
+        timeslots_input = [2, 2, 2, 2, 4, 4, 4, 4]
+        bursts_input = [
+            "0001100000010010011110111110011111000000001010001111000000001000110101110010000011010111100101101010000001111010100010110111101011101011100000101000",
+            "0001000101111101111110000010100001011011111010111110101011101000110101110010000011010111110110111101101111110000011011010111011111001011101000011000",
+            "0000001000011110111110101011001000110000000000110110101100011000110101110010000011010111001010100101011111001000111100000100000111111000000101110000",
+            "0001101010111110010001010110101100000011101100011111110100101000110101110010000011010111111000000001010010111001111111011001000000001001000011101000",
+            "0001111101101110110000010100100111000001001000100000001111100011100010111000101110001010111010010100011001100111001111010011111000100101111101010000",
+            "0001111101101110110000010100100111000001001000100000001111100011100010111000101110001010111010010100011001100111001111010011111000100101111101010000",
+            "0001111101101110110000010100100111000001001000100000001111100011100010111000101110001010111010010100011001100111001111010011111000100101111101010000",
+            "0001111101101110110000010100100111000001001000100000001111100011100010111000101110001010111010010100011001100111001111010011111000100101111101010000"
+            
+        ]
+        
+        expected_lines = [
+            "test_006: 2569043 3967625: 110000001001001111011111001111100000000101000111100000000100101101010000001111010100010110111101011101011100000101",
+            "test_006: 2569044 3967658: 100010111110111111000001010000101101111101011111010101110110110111101101111110000011011010111011111001011101000011",
+            "test_006: 2569045 3967691: 000100001111011111010101100100011000000000011011010110001001010100101011111001000111100000100000111111000000101110",
+            "test_006: 2569046 3967724: 110101011111001000101011010110000001110110001111111010010111000000001010010111001111111011001000000001001000011101",
+            "test_006: 1099602 1699146: 111110110111011000001010010011100000100100010000000111110111010010100011001100111001111010011111000100101111101010",
+            "test_006: 1099603 1699179: 111110110111011000001010010011100000100100010000000111110111010010100011001100111001111010011111000100101111101010",
+            "test_006: 1099604 1699212: 111110110111011000001010010011100000100100010000000111110111010010100011001100111001111010011111000100101111101010",
+            "test_006: 1099605 1699245: 111110110111011000001010010011100000100100010000000111110111010010100011001100111001111010011111000100101111101010"
+        ]
+        
+        src = grgsm.burst_source(framenumbers_input, timeslots_input, bursts_input)
+        printer = grgsm.bursts_printer(pmt.intern("test_006: "), True, True, True, False)
+        self.tb.msg_connect(src, "out", printer, "bursts")
+        self.tb.run()
+
+        self.assertEqual(self.getOutput(), self.getOutputExpected(expected_lines))
+
+    def test_007_payload_prefix_fnr_fcount (self):
+        """
+            Payload only, no prefix, with frame number, frame count, and ignoring dummy bursts
+            Bursts 4-7 are dummy bursts
+        """
+        framenumbers_input = [2569043, 2569044, 2569045, 2569046, 1099602, 1099603, 1099604, 1099605]
+        timeslots_input = [2, 2, 2, 2, 4, 4, 4, 4]
+        bursts_input = [
+            "0001100000010010011110111110011111000000001010001111000000001000110101110010000011010111100101101010000001111010100010110111101011101011100000101000",
+            "0001000101111101111110000010100001011011111010111110101011101000110101110010000011010111110110111101101111110000011011010111011111001011101000011000",
+            "0000001000011110111110101011001000110000000000110110101100011000110101110010000011010111001010100101011111001000111100000100000111111000000101110000",
+            "0001101010111110010001010110101100000011101100011111110100101000110101110010000011010111111000000001010010111001111111011001000000001001000011101000",
+            "0001111101101110110000010100100111000001001000100000001111100011100010111000101110001010111010010100011001100111001111010011111000100101111101010000",
+            "0001111101101110110000010100100111000001001000100000001111100011100010111000101110001010111010010100011001100111001111010011111000100101111101010000",
+            "0001111101101110110000010100100111000001001000100000001111100011100010111000101110001010111010010100011001100111001111010011111000100101111101010000",
+            "0001111101101110110000010100100111000001001000100000001111100011100010111000101110001010111010010100011001100111001111010011111000100101111101010000"
+            
+        ]
+        
+        expected_lines = [
+            "test_007: 2569043 3967625: 110000001001001111011111001111100000000101000111100000000100101101010000001111010100010110111101011101011100000101",
+            "test_007: 2569044 3967658: 100010111110111111000001010000101101111101011111010101110110110111101101111110000011011010111011111001011101000011",
+            "test_007: 2569045 3967691: 000100001111011111010101100100011000000000011011010110001001010100101011111001000111100000100000111111000000101110",
+            "test_007: 2569046 3967724: 110101011111001000101011010110000001110110001111111010010111000000001010010111001111111011001000000001001000011101"
+        ]
+        
+        src = grgsm.burst_source(framenumbers_input, timeslots_input, bursts_input)
+        printer = grgsm.bursts_printer(pmt.intern("test_007: "), True, True, True, True)
+        self.tb.msg_connect(src, "out", printer, "bursts")
+        self.tb.run()
+
+        self.assertEqual(self.getOutput(), self.getOutputExpected(expected_lines))
+        
+    def test_008_complete_prefix_fnr_fcount (self):
+        """
+            Complete bursts, no prefix, with frame number, frame count, and ignoring dummy bursts
+            Bursts 4-7 are dummy bursts
+        """
+        framenumbers_input = [2569043, 2569044, 2569045, 2569046, 1099602, 1099603, 1099604, 1099605]
+        timeslots_input = [2, 2, 2, 2, 4, 4, 4, 4]
+        bursts_input = [
+            "0001100000010010011110111110011111000000001010001111000000001000110101110010000011010111100101101010000001111010100010110111101011101011100000101000",
+            "0001000101111101111110000010100001011011111010111110101011101000110101110010000011010111110110111101101111110000011011010111011111001011101000011000",
+            "0000001000011110111110101011001000110000000000110110101100011000110101110010000011010111001010100101011111001000111100000100000111111000000101110000",
+            "0001101010111110010001010110101100000011101100011111110100101000110101110010000011010111111000000001010010111001111111011001000000001001000011101000",
+            "0001111101101110110000010100100111000001001000100000001111100011100010111000101110001010111010010100011001100111001111010011111000100101111101010000",
+            "0001111101101110110000010100100111000001001000100000001111100011100010111000101110001010111010010100011001100111001111010011111000100101111101010000",
+            "0001111101101110110000010100100111000001001000100000001111100011100010111000101110001010111010010100011001100111001111010011111000100101111101010000",
+            "0001111101101110110000010100100111000001001000100000001111100011100010111000101110001010111010010100011001100111001111010011111000100101111101010000"
+            
+        ]
+        
+        expected_lines = [
+            "test_008: 2569043 3967625: 0001100000010010011110111110011111000000001010001111000000001000110101110010000011010111100101101010000001111010100010110111101011101011100000101000",
+            "test_008: 2569044 3967658: 0001000101111101111110000010100001011011111010111110101011101000110101110010000011010111110110111101101111110000011011010111011111001011101000011000",
+            "test_008: 2569045 3967691: 0000001000011110111110101011001000110000000000110110101100011000110101110010000011010111001010100101011111001000111100000100000111111000000101110000",
+            "test_008: 2569046 3967724: 0001101010111110010001010110101100000011101100011111110100101000110101110010000011010111111000000001010010111001111111011001000000001001000011101000"
+        ]
+        
+        src = grgsm.burst_source(framenumbers_input, timeslots_input, bursts_input)
+        printer = grgsm.bursts_printer(pmt.intern("test_008: "), True, True, False, True)
+        self.tb.msg_connect(src, "out", printer, "bursts")
+        self.tb.run()
+
+        self.assertEqual(self.getOutput(), self.getOutputExpected(expected_lines))
+
+
+if __name__ == '__main__':
+    gr_unittest.run(qa_burst_printer, "qa_burst_printer.xml")
diff --git a/python/qa_decryption.py b/python/qa_decryption.py
index cf228ae..08f0915 100755
--- a/python/qa_decryption.py
+++ b/python/qa_decryption.py
@@ -56,9 +56,9 @@
         key = [0x32,0xE5,0x45,0x53,0x20,0x8C,0xE0,0x00]
         a5_version = 1
 
-        src = grgsm.burst_source_qa(framenumbers_input, timeslots_input, bursts_input)
+        src = grgsm.burst_source(framenumbers_input, timeslots_input, bursts_input)
         decryption = grgsm.decryption((key), a5_version)
-        dst = grgsm.burst_sink_qa()
+        dst = grgsm.burst_sink()
 
         self.tb.msg_connect(src, "out", decryption, "bursts")
         self.tb.msg_connect(decryption, "bursts", dst, "in")
@@ -97,9 +97,9 @@
         key = [0xAD,0x6A,0x3E,0xC2,0xB4,0x42,0xE4,0x00]
         a5_version = 1
         
-        src = grgsm.burst_source_qa(framenumbers_input, timeslots_input, bursts_input)
+        src = grgsm.burst_source(framenumbers_input, timeslots_input, bursts_input)
         decryption = grgsm.decryption((key), a5_version)
-        dst = grgsm.burst_sink_qa()
+        dst = grgsm.burst_sink()
 
         self.tb.msg_connect(src, "out", decryption, "bursts")
         self.tb.msg_connect(decryption, "bursts", dst, "in")
@@ -138,9 +138,9 @@
         key = [0x41,0xBC,0x19,0x30,0xB6,0x31,0x8A,0xC8]
         a5_version = 3
         
-        src = grgsm.burst_source_qa(framenumbers_input, timeslots_input, bursts_input)
+        src = grgsm.burst_source(framenumbers_input, timeslots_input, bursts_input)
         decryption = grgsm.decryption((key), a5_version)
-        dst = grgsm.burst_sink_qa()
+        dst = grgsm.burst_sink()
 
         self.tb.msg_connect(src, "out", decryption, "bursts")
         self.tb.msg_connect(decryption, "bursts", dst, "in")
@@ -179,9 +179,9 @@
         key = [0xAD,0x2C,0xB3,0x83,0x2F,0x4A,0x6C,0xF1]
         a5_version = 3
         
-        src = grgsm.burst_source_qa(framenumbers_input, timeslots_input, bursts_input)
+        src = grgsm.burst_source(framenumbers_input, timeslots_input, bursts_input)
         decryption = grgsm.decryption((key), a5_version)
-        dst = grgsm.burst_sink_qa()
+        dst = grgsm.burst_sink()
 
         self.tb.msg_connect(src, "out", decryption, "bursts")
         self.tb.msg_connect(decryption, "bursts", dst, "in")
diff --git a/python/qa_message_printer.py b/python/qa_message_printer.py
new file mode 100755
index 0000000..4efaaef
--- /dev/null
+++ b/python/qa_message_printer.py
@@ -0,0 +1,166 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# @file
+# @author Roman Khassraf <rkhassraf@gmail.com>
+# @section LICENSE
+# 
+# Gr-gsm 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.
+# 
+# Gr-gsm 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 gr-gsm; 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, blocks
+import grgsm
+import os
+import pmt
+import sys
+import tempfile
+
+class qa_message_printer (gr_unittest.TestCase):
+   
+    def setUp (self):
+        self.tb = gr.top_block()
+        self.tmpfile = tempfile.NamedTemporaryFile()
+        self.prevfd = os.dup(sys.stdout.fileno())
+        os.dup2(self.tmpfile.fileno(), sys.stdout.fileno())
+        self.prev = sys.stdout
+        sys.stdout = os.fdopen(self.prevfd, "w")
+        
+    def tearDown (self):
+        self.tb = None
+        os.dup2(self.prevfd, self.prev.fileno())
+        sys.stdout = self.prev
+        self.tmpfile.close()
+        
+    def getOutput(self):
+        self.tmpfile.seek(0)
+        return self.tmpfile.read()
+    
+    def getOutputExpected(self, expected_lines):
+        out = ""
+        for l in expected_lines:
+            out = out + l + "\n"
+        return out
+        
+    def test_001_no_prefix_no_header (self):
+        """
+            Four messages, without any prefix, no gsmtap header
+        """
+        msgs_input = [
+            "02 04 01 00 00 00 c9 00 00 1d 3c e5 02 00 01 00 15 06 21 00 01 f0 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b",
+            "02 04 01 00 00 00 ca 00 00 1d 3c e9 02 00 02 00 15 06 21 00 01 f0 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b",
+            "02 04 01 00 00 00 cb 00 00 1d 3d 0e 01 00 00 00 59 06 1a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff e5 04 00",
+            "02 04 01 00 00 00 cb 00 00 1d 3d 12 02 00 00 00 15 06 21 00 01 f0 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b"
+        ]
+        
+        # there is a whitespace at the beginning of message_printer output
+        msgs_expected = [
+            " 15 06 21 00 01 f0 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b",
+            " 15 06 21 00 01 f0 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b",
+            " 59 06 1a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff e5 04 00",
+            " 15 06 21 00 01 f0 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b"
+        ]
+        
+        src = grgsm.message_source(msgs_input)
+        printer = grgsm.message_printer(pmt.intern(""), False)
+        self.tb.msg_connect(src, "msgs", printer, "msgs")
+        self.tb.run()
+
+        self.assertEqual(self.getOutput(), self.getOutputExpected(msgs_expected))
+
+
+    def test_002_prefix_no_header (self):
+        """
+            Four messages, with prefix "test_002:", no gsmtap header
+        """
+        msgs_input = [
+            "02 04 01 00 00 00 c9 00 00 1d 3c e5 02 00 01 00 15 06 21 00 01 f0 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b",
+            "02 04 01 00 00 00 ca 00 00 1d 3c e9 02 00 02 00 15 06 21 00 01 f0 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b",
+            "02 04 01 00 00 00 cb 00 00 1d 3d 0e 01 00 00 00 59 06 1a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff e5 04 00",
+            "02 04 01 00 00 00 cb 00 00 1d 3d 12 02 00 00 00 15 06 21 00 01 f0 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b"
+        ]
+        
+        msgs_expected = [
+            "test_002: 15 06 21 00 01 f0 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b",
+            "test_002: 15 06 21 00 01 f0 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b",
+            "test_002: 59 06 1a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff e5 04 00",
+            "test_002: 15 06 21 00 01 f0 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b"
+        ]
+        
+        src = grgsm.message_source(msgs_input)
+        printer = grgsm.message_printer(pmt.intern("test_002:"), False)
+        self.tb.msg_connect(src, "msgs", printer, "msgs")
+        self.tb.run()
+
+        self.assertEqual(self.getOutput(), self.getOutputExpected(msgs_expected))
+
+
+    def test_003_no_prefix_header (self):
+        """
+            Four messages, without any prefix, with gsmtap header
+        """
+        msgs_input = [
+            "02 04 01 00 00 00 c9 00 00 1d 3c e5 02 00 01 00 15 06 21 00 01 f0 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b",
+            "02 04 01 00 00 00 ca 00 00 1d 3c e9 02 00 02 00 15 06 21 00 01 f0 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b",
+            "02 04 01 00 00 00 cb 00 00 1d 3d 0e 01 00 00 00 59 06 1a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff e5 04 00",
+            "02 04 01 00 00 00 cb 00 00 1d 3d 12 02 00 00 00 15 06 21 00 01 f0 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b"
+        ]
+        
+        # there is a whitespace at the beginning of message_printer output
+        msgs_expected = [
+            " 02 04 01 00 00 00 c9 00 00 1d 3c e5 02 00 01 00 15 06 21 00 01 f0 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b",
+            " 02 04 01 00 00 00 ca 00 00 1d 3c e9 02 00 02 00 15 06 21 00 01 f0 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b",
+            " 02 04 01 00 00 00 cb 00 00 1d 3d 0e 01 00 00 00 59 06 1a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff e5 04 00",
+            " 02 04 01 00 00 00 cb 00 00 1d 3d 12 02 00 00 00 15 06 21 00 01 f0 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b"
+        ]
+        
+        src = grgsm.message_source(msgs_input)
+        printer = grgsm.message_printer(pmt.intern(""), True)
+        self.tb.msg_connect(src, "msgs", printer, "msgs")
+        self.tb.run()
+
+        self.assertEqual(self.getOutput(), self.getOutputExpected(msgs_expected))
+        
+
+    def test_004_prefix_header (self):
+        """
+            Four messages, with prefix "test_004:", with gsmtap header
+        """
+        msgs_input = [
+            "02 04 01 00 00 00 c9 00 00 1d 3c e5 02 00 01 00 15 06 21 00 01 f0 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b",
+            "02 04 01 00 00 00 ca 00 00 1d 3c e9 02 00 02 00 15 06 21 00 01 f0 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b",
+            "02 04 01 00 00 00 cb 00 00 1d 3d 0e 01 00 00 00 59 06 1a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff e5 04 00",
+            "02 04 01 00 00 00 cb 00 00 1d 3d 12 02 00 00 00 15 06 21 00 01 f0 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b"
+        ]
+        
+        # there is a whitespace at the beginning of message_printer output
+        msgs_expected = [
+            "test_004: 02 04 01 00 00 00 c9 00 00 1d 3c e5 02 00 01 00 15 06 21 00 01 f0 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b",
+            "test_004: 02 04 01 00 00 00 ca 00 00 1d 3c e9 02 00 02 00 15 06 21 00 01 f0 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b",
+            "test_004: 02 04 01 00 00 00 cb 00 00 1d 3d 0e 01 00 00 00 59 06 1a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff e5 04 00",
+            "test_004: 02 04 01 00 00 00 cb 00 00 1d 3d 12 02 00 00 00 15 06 21 00 01 f0 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b"
+        ]
+        
+        src = grgsm.message_source(msgs_input)
+        printer = grgsm.message_printer(pmt.intern("test_004:"), True)
+        self.tb.msg_connect(src, "msgs", printer, "msgs")
+        self.tb.run()
+
+        self.assertEqual(self.getOutput(), self.getOutputExpected(msgs_expected))
+        
+        
+if __name__ == '__main__':
+    gr_unittest.run(qa_message_printer, "qa_message_printer.xml")
+ 
diff --git a/swig/grgsm_swig.i b/swig/grgsm_swig.i
index b9dad13..9355998 100644
--- a/swig/grgsm_swig.i
+++ b/swig/grgsm_swig.i
@@ -27,10 +27,12 @@
 #include "grgsm/misc_utils/extract_immediate_assignment.h"
 #include "grgsm/misc_utils/message_printer.h"
 #include "grgsm/misc_utils/tmsi_dumper.h"
-#include "grgsm/misc_utils/burst_sink.h"
-#include "grgsm/misc_utils/burst_sink_qa.h"
-#include "grgsm/misc_utils/burst_source.h"
-#include "grgsm/misc_utils/burst_source_qa.h"
+#include "grgsm/misc_utils/burst_file_sink.h"
+#include "grgsm/misc_utils/burst_file_source.h"
+#include "grgsm/qa_utils/burst_sink.h"
+#include "grgsm/qa_utils/burst_source.h"
+#include "grgsm/qa_utils/message_source.h"
+#include "grgsm/qa_utils/message_sink.h"
 %}
 
 %include "grgsm/receiver/receiver.h"
@@ -64,14 +66,10 @@
 
 %include "grgsm/misc_utils/bursts_printer.h"
 GR_SWIG_BLOCK_MAGIC2(gsm, bursts_printer);
-%include "grgsm/misc_utils/burst_sink.h"
-GR_SWIG_BLOCK_MAGIC2(gsm, burst_sink);
-%include "grgsm/misc_utils/burst_source.h"
-GR_SWIG_BLOCK_MAGIC2(gsm, burst_source);
-%include "grgsm/misc_utils/burst_sink_qa.h"
-GR_SWIG_BLOCK_MAGIC2(gsm, burst_sink_qa);
-%include "grgsm/misc_utils/burst_source_qa.h"
-GR_SWIG_BLOCK_MAGIC2(gsm, burst_source_qa);
+%include "grgsm/misc_utils/burst_file_sink.h"
+GR_SWIG_BLOCK_MAGIC2(gsm, burst_file_sink);
+%include "grgsm/misc_utils/burst_file_source.h"
+GR_SWIG_BLOCK_MAGIC2(gsm, burst_file_source);
 %include "grgsm/misc_utils/extract_system_info.h"
 GR_SWIG_BLOCK_MAGIC2(gsm, extract_system_info);
 %include "grgsm/misc_utils/extract_immediate_assignment.h"
@@ -84,3 +82,13 @@
 GR_SWIG_BLOCK_MAGIC2(gsm, message_printer);
 %include "grgsm/misc_utils/tmsi_dumper.h"
 GR_SWIG_BLOCK_MAGIC2(gsm, tmsi_dumper);
+
+%include "grgsm/qa_utils/burst_sink.h"
+GR_SWIG_BLOCK_MAGIC2(gsm, burst_sink);
+%include "grgsm/qa_utils/burst_source.h"
+GR_SWIG_BLOCK_MAGIC2(gsm, burst_source);
+%include "grgsm/qa_utils/message_source.h"
+GR_SWIG_BLOCK_MAGIC2(gsm, message_source);
+%include "grgsm/qa_utils/message_sink.h"
+GR_SWIG_BLOCK_MAGIC2(gsm, message_sink);
+