/* * camswclient.c - GStreamer softcam client * Copyright (C) 2007 Alessandro Decina * * Authors: * Alessandro Decina <alessandro@nnva.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #include <unistd.h> #include <stdio.h> #include <string.h> #include <gst/gst.h> #include "camswclient.h" #include "cam.h" #define GST_CAT_DEFAULT cam_debug_cat #define UNIX_PATH_MAX 108 CamSwClient * cam_sw_client_new (void) { CamSwClient *client = g_new0 (CamSwClient, 1); client->state = CAM_SW_CLIENT_STATE_CLOSED; return client; } static void reset_state (CamSwClient * client) { if (client->sock) close (client->sock); g_free (client->sock_path); } void cam_sw_client_free (CamSwClient * client) { g_return_if_fail (client != NULL); if (client->state != CAM_SW_CLIENT_STATE_CLOSED) GST_WARNING ("client not in CLOSED state when free'd"); reset_state (client); g_free (client); } gboolean cam_sw_client_open (CamSwClient * client, const char *sock_path) { struct sockaddr_un addr; int ret; g_return_val_if_fail (client != NULL, FALSE); g_return_val_if_fail (client->state == CAM_SW_CLIENT_STATE_CLOSED, FALSE); g_return_val_if_fail (sock_path != NULL, FALSE); g_return_val_if_fail (strlen (sock_path) >= sizeof (addr.sun_path), FALSE); addr.sun_family = AF_UNIX; strncpy (addr.sun_path, sock_path, sizeof (addr.sun_path)); GST_INFO ("connecting to softcam socket: %s", sock_path); if ((client->sock = socket (PF_UNIX, SOCK_STREAM, 0)) < 0) { GST_ERROR ("Failed to create a socket, error: %s", g_strerror (errno)); return FALSE; } ret = connect (client->sock, (struct sockaddr *) &addr, sizeof (struct sockaddr_un)); if (ret != 0) { GST_ERROR ("error opening softcam socket %s, error: %s", sock_path, g_strerror (errno)); return FALSE; } client->sock_path = g_strdup (sock_path); client->state = CAM_SW_CLIENT_STATE_OPEN; return TRUE; } void cam_sw_client_close (CamSwClient * client) { g_return_if_fail (client != NULL); g_return_if_fail (client->state == CAM_SW_CLIENT_STATE_OPEN); reset_state (client); client->state = CAM_SW_CLIENT_STATE_CLOSED; } static void send_ca_pmt (CamSwClient * client, GstMpegtsPMT * pmt, guint8 list_management, guint8 cmd_id) { guint8 *buffer; guint buffer_size; guint8 *ca_pmt; guint ca_pmt_size; guint length_field_len; guint header_len; ca_pmt = cam_build_ca_pmt (pmt, list_management, cmd_id, &ca_pmt_size); length_field_len = cam_calc_length_field_size (ca_pmt_size); header_len = 3 + length_field_len; buffer_size = header_len + ca_pmt_size; buffer = g_malloc0 (buffer_size); memcpy (buffer + header_len, ca_pmt, ca_pmt_size); /* ca_pmt resource_id */ buffer[0] = 0x9F; buffer[1] = 0x80; buffer[2] = 0x32; cam_write_length_field (&buffer[3], ca_pmt_size); if (write (client->sock, buffer, buffer_size) == -1) { GST_WARNING ("write failed when sending PMT with error: %s (%d)", g_strerror (errno), errno); } g_free (ca_pmt); g_free (buffer); } void cam_sw_client_set_pmt (CamSwClient * client, GstMpegtsPMT * pmt) { g_return_if_fail (client != NULL); g_return_if_fail (pmt != NULL); return send_ca_pmt (client, pmt, 0x03 /* only */ , 0x01 /* ok_descrambling */ ); } void cam_sw_client_update_pmt (CamSwClient * client, GstMpegtsPMT * pmt) { g_return_if_fail (client != NULL); g_return_if_fail (pmt != NULL); return send_ca_pmt (client, pmt, 0x05 /* update */ , 0x01 /* ok_descrambling */ ); }