/gyachi-1.2.11/client/webcam.c
C | 368 lines | 243 code | 59 blank | 66 comment | 37 complexity | 514823f40a635cbb20c3577e8b074fbb MD5 | raw file
Possible License(s): GPL-2.0
- /* Mainly a wrapper for launching the external web cam
- viewer gyache-webcam, but handles the necessary
- Ymsg negotiations inside Gyach */
- /*****************************************************************************
- * webcam.c
- *
- * This program 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 2 of the
- * License, or (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- *
- * Copyright (C) 2003-2005, Erica Andrews
- * (Phrozensmoke ['at'] yahoo.com)
- * http://phpaint.sourceforge.net/pyvoicechat/
- *
- * Released under the terms of the GPL.
- * *NO WARRANTY*
- *
- * VERY preliminary code for handling webcams - much of this code is
- * borrowed from the Ayttm/libyahoo2 projects
- *****************************************************************************/
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/wait.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
- #include <signal.h>
- #include <gtk/gtk.h>
- #include "config.h"
- #include "webcam.h"
- #include "sounds.h"
- #include "friends.h"
- #include "profname.h"
- #include "interface.h"
- #include "users.h"
- #include "gyachi_notebook.h"
- #include "util.h"
- #include "gyach.h"
- #include "gy_config.h"
- #include "gyachi_lib.h"
- const char *uploader_name = "gyachi-upload";
- const char *webcam_name = "gyachi-webcam";
- char *lastcamwho =NULL;
- int launch_my_cam=0;
- int my_cam_is_on=0;
- GList *launchers = NULL;
- void yahoo_webcam_get_feed(char *who)
- {
- if (!who) {return;}
- if (lastcamwho) {free(lastcamwho); lastcamwho=NULL; launch_my_cam=0;}
- if (!enable_webcam_features) {
- show_ok_dialog(_("Sorry, You have the webcam feature disabled."));
- return;
- }
- /* This is REALLY stupid, Yahoo will send us a webcam key with NO name
- attached, so all we can do is save the last requested name and hope
- they match up! */
- lastcamwho=strdup(who);
- if (!strcasecmp(lastcamwho, get_default_profile_name())) {
- launch_my_cam=1;
- ymsg_get_webcam(ymsg_sess, NULL); /* get the webcam-server for broadcasting */
- }
- else {
- ymsg_get_webcam(ymsg_sess, lastcamwho);
- }
- }
- char *make_webcam_friends( ) {
- GList *this_friend;
- char *frmsg=malloc(10240);
- if (!frmsg) {return strdup("");}
- sprintf( frmsg, "%s", "");
- this_friend = friend_list;
- while( this_friend ) {
- if (strlen(frmsg)>10155) {break;} /* avoid buffer overflow */
- if ( this_friend != friend_list ) { strcat( frmsg, "," );}
- strcat( frmsg, this_friend->data );
- this_friend = g_list_next( this_friend );
- }
- return frmsg;
- }
- void my_sig_child_handler(int sig, siginfo_t *my_siginfo, void *arg)
- {
- int pid = my_siginfo->si_pid;
- int status;
- waitpid(pid, &status, 0);
- /* remove pid from launcher list.
- * If launcher list empties, then reset broadcast flag
- */
- launchers = g_list_remove(launchers, (void *)pid);
- if (g_list_length(launchers) == 0) {
- my_cam_is_on = -1;
- }
- }
- void yahoo_process_webcam_key(char *key, char *server)
- {
- struct stat sbuf;
- char *(pieces[4]);
- char *launcher=NULL;
- static int handler_installed = 0;
- struct sigaction my_sigaction;
- sigset_t my_blocked_sigs, old_blocked_sigs;
- pid_t pid;
- if (!enable_webcam_features) {
- return;
- }
- if (!key) {
- return;
- }
- if (!lastcamwho) {
- return;
- }
- if (!handler_installed) {
- memset(&my_sigaction, 0, sizeof(my_sigaction));
- my_sigaction.sa_sigaction = my_sig_child_handler;
- my_sigaction.sa_flags = SA_SIGINFO;
- sigaction(SIGCHLD, &my_sigaction, 0);
- }
- if (launch_my_cam) { /* launch the webcam uploader */
- char *myfriends=NULL;
-
- pieces[0]=EXPANDED_LIBEXECDIR;
- pieces[1]="/";
- pieces[2]=(char *)uploader_name;
- pieces[3]=NULL;
- launcher=build_string(pieces);
- if ( stat( launcher, &sbuf )) {
- char *wmsg;
- char *msg = _("The GyachI external webcam broadcaster could not be found");
- wmsg = malloc(strlen(msg) + strlen(launcher) + 4);
- sprintf(wmsg, "%s:\n\n%s", msg, launcher);
- show_ok_dialog(wmsg);
- free(wmsg);
- free(lastcamwho);
- lastcamwho=NULL;
- launch_my_cam=0;
- free(launcher);
- launcher=NULL;
- return;
- }
-
- /* TODO: add friends list as last argument */
- if (!webcam_device) {
- webcam_device=strdup("/dev/video0");
- }
- myfriends=make_webcam_friends( );
- /* block signals before forking.
- * This will prevent a race condition of
- * the child starting, and exiting *BEFORE* the
- * parent starts up.
- */
- sigfillset(&my_blocked_sigs);
- sigprocmask(SIG_BLOCK, &my_blocked_sigs, &old_blocked_sigs);
- pid=fork();
- if (pid == 0) {
- /* we're the child
- * re-enable our signal mask, and then exec the launcher.
- */
- sigprocmask(SIG_BLOCK, &old_blocked_sigs, 0);
- execl(launcher,
- launcher,
- get_default_profile_name(),
- key,
- webcam_device,
- server,
- myfriends,
- NULL);
- }
- /* we're the parent
- * Add child PID to glist of launchers. Be sure to
- * block signals (in particular SIG CHILD) while we do this
- */
- my_cam_is_on = 1;
- launchers = g_list_append(launchers, (void *)pid);
- sigprocmask(SIG_BLOCK, &old_blocked_sigs, 0);
- free(launcher);
- launcher=NULL;
- free(lastcamwho);
- lastcamwho=NULL;
- free(myfriends);
- myfriends=NULL;
- if (show_cam_is_on) {
- char *launch_status;
- launch_status=malloc(strlen(webcamtext)+4);
- strcpy(launch_status, "99:");
- strcpy(launch_status+3, webcamtext);
- ymsg_away(ymsg_sess, launch_status);
- free(launch_status);
- launch_status=NULL;
- }
- launch_my_cam=0;
- return ;
- }
- else {
- /* run EXTERNAL VIEWER HERE */
- if (! webcam_viewer_app) {
- webcam_viewer_app=strdup("GyachI Webcam");
- }
- /* check to see if the external viewer is there */
- pieces[0]=EXPANDED_LIBEXECDIR;
- pieces[1]="/";
- pieces[2]=(char *)webcam_name;
- pieces[3]=NULL;
- launcher=build_string(pieces);
- if ( stat( launcher, &sbuf )) {
- char *wmsg;
- char *msg = _("The GyachI external webcam viewer could not be found");
- wmsg = malloc(strlen(msg) + strlen(launcher) + 4);
- sprintf(wmsg, "%s:\n\n%s", msg, launcher);
- show_ok_dialog(wmsg);
- return;
- }
- pid=fork();
- if (pid == 0) {
- /* we're the child
- * re-enable our signal mask, and then exec the launcher.
- */
- execl(launcher,
- launcher,
- lastcamwho,
- get_default_profile_name(),
- key,
- server,
- NULL);
- }
- free(launcher);
- launcher=NULL;
- free(lastcamwho);
- lastcamwho=NULL;
- }
- }
- void gyache_yahoo_webcam_invite_callback(char *who, int result)
- {
- if (!enable_webcam_features) {
- return;
- }
- if (result) {
- ymsg_webcam_invite_accept( ymsg_sess, who);
- yahoo_webcam_get_feed(who);
- }
- else {
- ymsg_webcam_invite_reject( ymsg_sess, who);
- }
- }
- void on_webcam_invite_accept (GtkWidget *button, gpointer user_data)
- {
- GtkWidget *tmp_widget;
- char *who=NULL;
- who = g_object_get_data(G_OBJECT(button), "who" );
- if (who) {gyache_yahoo_webcam_invite_callback(who,1); free(who);}
- tmp_widget=g_object_get_data(G_OBJECT(button), "mywindow");
- if (tmp_widget) {gtk_widget_destroy(tmp_widget);}
- }
- void on_webcam_invite_reject (GtkWidget *button, gpointer user_data)
- {
- GtkWidget *tmp_widget;
- char *who=NULL;
- who = g_object_get_data(G_OBJECT(button), "who" );
- if (who) {gyache_yahoo_webcam_invite_callback(who,0); free(who);}
- tmp_widget=g_object_get_data(G_OBJECT(button), "mywindow");
- if (tmp_widget) {gtk_widget_destroy(tmp_widget);}
- }
- void yahoo_webcam_invite_msg(char *who)
- {
- char buff[256];
- GtkWidget *okbutton=NULL;
- GtkWidget *cbutton=NULL;
- GtkWidget *parent; /* either pm of "who", or main chat window */
- if (!enable_webcam_features) {
- /* we aren't allowing webcam, so auto-reject invites */
- /* packet_handler should catch this first, but just in case */
- ymsg_webcam_invite_reject( ymsg_sess, who);
- return;
- }
-
- snprintf(buff, 254, _("The yahoo user <b>%s</b> has invited you to view their webcam. Do you want to accept?"), who);
- parent = find_pms_window(who);
- if (!parent) parent=chat_window;
- gtk_window_present(GTK_WINDOW(parent));
- okbutton=show_confirm_dialog_config_p(parent, buff, "Yes", "No", 0);
- if (!okbutton) {ymsg_webcam_invite_reject( ymsg_sess, who); return;}
- g_signal_connect(G_OBJECT(okbutton), "clicked",
- G_CALLBACK (on_webcam_invite_accept), NULL);
- g_object_set_data(G_OBJECT(okbutton), "who", strdup(who));
- cbutton=g_object_get_data(G_OBJECT(okbutton), "cancel" );
- if (cbutton) {
- g_signal_connect(G_OBJECT(cbutton), "clicked",
- G_CALLBACK (on_webcam_invite_reject), NULL);
- g_object_set_data(G_OBJECT(cbutton), "who", strdup(who));
- }
- play_sound_event(SOUND_EVENT_OTHER);
- }
- /* This should be handled in GyachE, not in the external cam viewer:
- A viewer sent a Ymsg packet accepting/rejecting
- a cam invite we sent them - this is already handled by packet_handler.c
- appropriately */
- /*
- void yahoo_webcam_invite_reply(char *from, int accept)
- {
- }
- */