rec_tech.c
上传用户:ledjyj
上传日期:2014-08-27
资源大小:2639k
文件大小:7k
源码类别:

驱动编程

开发平台:

Unix_Linux

  1. /*
  2.  *  This program is free software; you can redistribute it and/or modify
  3.  *  it under the terms of the GNU General Public License as published by
  4.  *  the Free Software Foundation; either version 2 of the License, or
  5.  *  (at your option) any later version.
  6.  *
  7.  *  This program is distributed in the hope that it will be useful,
  8.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  9.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10.  *  GNU Library General Public License for more details.
  11.  *
  12.  *  You should have received a copy of the GNU General Public License
  13.  *  along with this program; if not, write to the Free Software
  14.  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  15.  */
  16. #include "rec_tech.h"
  17. #include <gnome.h>
  18. #include <profiles/audio-profile.h>
  19. #include <sys/types.h>
  20. #include <sys/stat.h>
  21. #include <unistd.h>
  22. #include <fcntl.h>
  23. static GstElement*
  24. my_gst_gconf_render_bin_from_description(const gchar * description);
  25. static GstPad*
  26. my_gst_bin_find_unconnected_pad(GstBin* bin, GstPadDirection direction);
  27. static void error_cb(GstBus *bus, GstMessage *message, gpointer user_data)
  28. {
  29. GError *error = NULL;
  30. GstElement *pipeline = user_data;
  31. g_assert(pipeline);
  32. /* Make sure the pipeline is not running any more */
  33. gst_element_set_state (pipeline, GST_STATE_NULL);
  34. gst_message_parse_error(message, &error, NULL);
  35. show_error_message(_("GStreamer runtime error."), error->message);
  36. g_error_free(error);
  37. }
  38. Recording*
  39. recording_start(const char* filename)
  40. {
  41. GMAudioProfile *profile;
  42. GstElement *pipeline, *oss_src, *encoder, *filesink;
  43. pipeline = oss_src = encoder = filesink = NULL;
  44. profile = gm_audio_profile_lookup(rec_settings.profile);
  45. g_assert(profile);
  46. pipeline = gst_pipeline_new("gnomeradio-record-pipeline");
  47. if (!pipeline) {
  48. show_error_message(_("Could not create GStreamer pipeline."),
  49. _("Check your Gstreamer installation!"));
  50. goto error;
  51. }
  52. oss_src = gst_element_factory_make("osssrc", "oss-source");
  53. if (!oss_src) {
  54. show_error_message(_("Could not open Gstreamer OSS Source."),
  55. _("Verify your Gstreamer OSS subsystem installation!"));
  56. goto error;
  57. }
  58. GstBus *bus = gst_element_get_bus(pipeline);
  59. gst_bus_add_signal_watch(bus);
  60. g_signal_connect(G_OBJECT(bus), "message::error", G_CALLBACK(error_cb), pipeline);
  61. char* pipeline_str = g_strdup_printf("audioconvert ! %s", gm_audio_profile_get_pipeline(profile));
  62. encoder = my_gst_gconf_render_bin_from_description(pipeline_str);
  63. g_free(pipeline_str);
  64. if (!encoder) {
  65. char *caption = g_strdup_printf(_("Could not create encoder "%s"."), gm_audio_profile_get_name (profile));
  66. show_error_message(caption,
  67. _("Verify your Gstreamer plugins installation!"));
  68. g_free(caption);
  69. goto error;
  70. }
  71. /* Write to disk */
  72. filesink = gst_element_factory_make("filesink", "file-sink");
  73. if (!filesink) {
  74. show_error_message(_("Could not create Gstreamer filesink."),
  75. _("Check your Gstreamer installation!"));
  76. goto error;
  77. }
  78. /* Add the elements to the pipeline */
  79. gst_bin_add_many(GST_BIN(pipeline), oss_src, encoder, filesink, NULL);
  80. /* Link it all together */
  81. if (!gst_element_link_many(oss_src, encoder, filesink, NULL)) {
  82. g_warning("Could not link elements. This is bad!n");
  83. goto error;
  84. }
  85. char* path = g_strdup_printf("%s.%s", filename, gm_audio_profile_get_extension(profile));
  86. g_object_set(G_OBJECT(filesink), "location", path, NULL);
  87. gst_element_set_state(pipeline, GST_STATE_PLAYING);
  88. Recording *recording = g_malloc0(sizeof(Recording));
  89. recording->filename = path;
  90. recording->pipeline = pipeline;
  91. return recording;
  92. error:
  93. if (pipeline)
  94. gst_object_unref(GST_OBJECT(pipeline));
  95. if (oss_src)
  96. gst_object_unref(GST_OBJECT(oss_src));
  97. if (encoder)
  98. gst_object_unref(GST_OBJECT(encoder));
  99. if (filesink)
  100. gst_object_unref(GST_OBJECT(filesink));
  101. return NULL;
  102. }
  103. void
  104. recording_stop(Recording *recording)
  105. {
  106. g_assert(recording);
  107. GstState state;
  108. gst_element_get_state(recording->pipeline, &state, NULL, GST_CLOCK_TIME_NONE);
  109. if (state != GST_STATE_PLAYING) {
  110.      g_print("Ups!n");
  111. } else {
  112. gst_element_set_state(recording->pipeline, GST_STATE_NULL);
  113. }
  114. gst_object_unref(GST_OBJECT(recording->pipeline));
  115. g_free(recording->filename);
  116. g_free(recording->station);
  117. g_free(recording);
  118. }
  119. /* Stolen from gst-plugins-good/ext/gconf/gconf.c */
  120. static GstPad *
  121. my_gst_bin_find_unconnected_pad (GstBin * bin, GstPadDirection direction)
  122. {
  123.   GstPad *pad = NULL;
  124.   GList *elements = NULL;
  125.   const GList *pads = NULL;
  126.   GstElement *element = NULL;
  127.   GST_OBJECT_LOCK (bin);
  128.   elements = bin->children;
  129.   /* traverse all elements looking for unconnected pads */
  130.   while (elements && pad == NULL) {
  131.     element = GST_ELEMENT (elements->data);
  132.     GST_OBJECT_LOCK (element);
  133.     pads = element->pads;
  134.     while (pads) {
  135.       GstPad *testpad = GST_PAD (pads->data);
  136.       /* check if the direction matches */
  137.       if (GST_PAD_DIRECTION (testpad) == direction) {
  138.         GST_OBJECT_LOCK (testpad);
  139.         if (GST_PAD_PEER (testpad) == NULL) {
  140.           GST_OBJECT_UNLOCK (testpad);
  141.           /* found it ! */
  142.           pad = testpad;
  143.           break;
  144.         }
  145.         GST_OBJECT_UNLOCK (testpad);
  146.       }
  147.       pads = g_list_next (pads);
  148.     }
  149.     GST_OBJECT_UNLOCK (element);
  150.     elements = g_list_next (elements);
  151.   }
  152.   GST_OBJECT_UNLOCK (bin);
  153.   return pad;
  154. }
  155. /* Stolen from gst-plugins-good/ext/gconf/gconf.c */
  156. static GstElement *
  157. my_gst_gconf_render_bin_from_description (const gchar * description)
  158. {
  159.   GstElement *bin = NULL;
  160.   GstPad *pad = NULL;
  161.   GError *error = NULL;
  162.   gchar *desc = NULL;
  163.   /* parse the pipeline to a bin */
  164.   desc = g_strdup_printf ("bin.( %s )", description);
  165.   bin = GST_ELEMENT (gst_parse_launch (desc, &error));
  166.   g_free (desc);
  167.   if (error) {
  168.     GST_ERROR ("gstgconf: error parsing pipeline %sn%sn",
  169.         description, error->message);
  170.     g_error_free (error);
  171.     return NULL;
  172.   }
  173.   /* find pads and ghost them if necessary */
  174.   if ((pad = my_gst_bin_find_unconnected_pad (GST_BIN (bin), GST_PAD_SRC))) {
  175.     gst_element_add_pad (bin, gst_ghost_pad_new ("src", pad));
  176.   }
  177.   if ((pad = my_gst_bin_find_unconnected_pad (GST_BIN (bin), GST_PAD_SINK))) {
  178.     gst_element_add_pad (bin, gst_ghost_pad_new ("sink", pad));
  179.   }
  180.   return bin;
  181. }
  182. /*
  183.  * Miscellanelous functions
  184.  */
  185. int get_file_size(char *filename)
  186. {
  187. struct stat buffer;
  188. g_assert(filename);
  189. if (lstat(filename, &buffer))
  190. return -1;
  191. return (int)buffer.st_size;
  192. }
  193. int check_filename(const char *filename)
  194. {
  195. int flags, retval;
  196. g_assert(filename);
  197. flags = O_RDWR | O_CREAT | O_APPEND;
  198. retval = open(filename, flags, 0664);
  199. if (retval < 0)
  200. {
  201. return 0;
  202. }
  203. close(retval);
  204. return 1;
  205. }