| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include "lynq_medial.h" | |
| #include <syslog.h> | |
| #include <gst/gst.h> | |
| #include <pthread.h> | |
| #include <cutils/properties.h> | |
| //#include "modem_afe_ctrl.h" | |
| #include <log/log.h> | |
| #define LOG_TAG "MEDIA_API" | |
| #define NV_VOLUME_NAME "ro.spk.volume.level" | |
| #define NV_MIC_VOLUME_NAME "ro.mic.volume.level" | |
| //static char *volume_rcv = "/tmp/libmodem-afe-ctrl/server_rcv"; | |
| static const int VOLUME_LEVEL_1 = 1;//0; | |
| static const int VOLUME_LEVEL_2 = 10923;//200; | |
| static const int VOLUME_LEVEL_3 = 21845;//209; | |
| static const int VOLUME_LEVEL_4 = 32767;//220; | |
| static const int VOLUME_LEVEL_5 = 43960;//234; | |
| static const int VOLUME_LEVEL_6 = 54612;//245; | |
| static const int VOLUME_LEVEL_7 = 65535;//255; | |
| static const int MIC_VOLUME_LEVEL_1 = 9; | |
| static const int MIC_VOLUME_LEVEL_2 = 19; | |
| static const int MIC_VOLUME_LEVEL_3 = 28; | |
| static const int MIC_VOLUME_LEVEL_4 = 37; | |
| static const int MIC_VOLUME_LEVEL_5 = 46; | |
| static const int MIC_VOLUME_LEVEL_6 = 55; | |
| static const int MIC_VOLUME_LEVEL_7 = 63; | |
| typedef void *MEDIA_HANDLE; | |
| static MEDIA_HANDLE g_media_handle=NULL; | |
| typedef struct { | |
| MEDIA_HANDLE handle; | |
| gint mute; | |
| gdouble volume; | |
| pthread_t thread; | |
| GMainLoop *loop; | |
| GstElement *playbin; | |
| guint bus_watch_id; | |
| GstState gst_cur_state; | |
| } MEDIA_PARAM_T; | |
| static gboolean | |
| bus_call (GstBus * bus, GstMessage * msg, gpointer datas) | |
| { | |
| GstState oldstate, newstate, pending; | |
| MEDIA_PARAM_T *param = (MEDIA_PARAM_T *)datas; | |
| GMainLoop *loop = param->loop; | |
| switch (GST_MESSAGE_TYPE (msg)) { | |
| case GST_MESSAGE_EOS:{ | |
| RLOGD ("End-of-stream\n"); | |
| g_main_loop_quit (loop); | |
| break; | |
| } | |
| case GST_MESSAGE_STATE_CHANGED: | |
| gst_message_parse_state_changed (msg, &oldstate, &newstate, &pending); | |
| param->gst_cur_state = newstate; | |
| break; | |
| case GST_MESSAGE_ERROR:{ | |
| gchar *debug; | |
| GError *err; | |
| gst_message_parse_error (msg, &err, &debug); | |
| g_printerr ("Debugging info: %s\n", (debug) ? debug : "none"); | |
| g_free (debug); | |
| RLOGD ("Error: %s\n", err->message); | |
| g_error_free (err); | |
| g_main_loop_quit (loop); | |
| break; | |
| } | |
| default: | |
| break; | |
| } | |
| return TRUE; | |
| } | |
| int lynq_get_mic_current_volume() | |
| { | |
| char cvolume_levle[5]= {0}; | |
| property_get(NV_MIC_VOLUME_NAME, cvolume_levle, "5"); | |
| printf("lynq_media_get_current_volume end :%s\n" ,cvolume_levle); | |
| return atoi(cvolume_levle); | |
| } | |
| static void lynq_set_mic_volume_to_nvram(const int volume_levle ) | |
| { | |
| char buf[5]; | |
| sprintf(buf, "%d", volume_levle); | |
| property_set(NV_MIC_VOLUME_NAME, buf); | |
| } | |
| static int lynq_set_mic_real_volume(const int real_volume) | |
| { | |
| char cmd[256]; | |
| RLOGD("mic real volume: %d \n", real_volume); | |
| sprintf(cmd, "amixer -c0 cset name=\"PGA Volume\" %d", real_volume); | |
| system(cmd); | |
| return 0; | |
| } | |
| static int get_mic_real_volume(const int volume_levle) | |
| { | |
| int real_volume; | |
| switch (volume_levle) { | |
| case MIC_VOLUME_LEVEL1: | |
| real_volume = MIC_VOLUME_LEVEL_1; | |
| break; | |
| case MIC_VOLUME_LEVEL2: | |
| real_volume = MIC_VOLUME_LEVEL_2; | |
| break; | |
| case MIC_VOLUME_LEVEL3: | |
| real_volume = MIC_VOLUME_LEVEL_3; | |
| break; | |
| case MIC_VOLUME_LEVEL4: | |
| real_volume = MIC_VOLUME_LEVEL_4; | |
| break; | |
| case MIC_VOLUME_LEVEL5: | |
| real_volume = MIC_VOLUME_LEVEL_5; | |
| break; | |
| case MIC_VOLUME_LEVEL6: | |
| real_volume = MIC_VOLUME_LEVEL_6; | |
| break; | |
| case MIC_VOLUME_LEVEL7: | |
| real_volume = MIC_VOLUME_LEVEL_7; | |
| break; | |
| default: | |
| syslog(LOG_ERR, "Not the correct parameter"); | |
| return 0; | |
| } | |
| return real_volume; | |
| } | |
| int lynq_set_mic_volume(const int volume) { | |
| int real_volume; | |
| if((volume>MIC_VOLUME_LEVEL7)||(volume<MIC_VOLUME_LEVEL1)) | |
| return 1; | |
| lynq_set_mic_volume_to_nvram(volume); | |
| real_volume = get_mic_real_volume(volume); | |
| lynq_set_mic_real_volume(real_volume); | |
| return 0; | |
| } | |
| int lynq_get_mic_volume(int* volume) { | |
| if(volume==NULL) | |
| { | |
| return 1; | |
| } | |
| (*volume) = lynq_get_mic_current_volume(); | |
| return 0; | |
| } | |
| int lynq_get_spk_current_volume() | |
| { | |
| char cvolume_levle[5] = {0}; | |
| property_get(NV_VOLUME_NAME, cvolume_levle, "5"); | |
| printf("lynq_media_get_current_volume end :%s\n" ,cvolume_levle); | |
| return atoi(cvolume_levle); | |
| } | |
| static void lynq_set_spk_volume_to_nvram(const int volume_levle ) | |
| { | |
| char buf[5] = {0}; | |
| sprintf(buf, "%d", volume_levle); | |
| property_set(NV_VOLUME_NAME, buf); | |
| } | |
| static int lynq_set_spk_real_volume(const int volume) | |
| { | |
| char cmd[256]; | |
| RLOGD("spk real volume: %d \n", volume); | |
| // sprintf(cmd, "amixer -c0 cset name=\"Playback Volume\" %d", volume); | |
| sprintf(cmd, "amixer cset name=\"Master Playback Volume\" %d", volume); | |
| system(cmd); | |
| return 0; | |
| } | |
| static int get_spk_real_volume(const int volume_levle) | |
| { | |
| int real_volume; | |
| switch (volume_levle) { | |
| case VOLUME_LEVEL1: | |
| real_volume = VOLUME_LEVEL_1; | |
| break; | |
| case VOLUME_LEVEL2: | |
| real_volume = VOLUME_LEVEL_2; | |
| break; | |
| case VOLUME_LEVEL3: | |
| real_volume = VOLUME_LEVEL_3; | |
| break; | |
| case VOLUME_LEVEL4: | |
| real_volume = VOLUME_LEVEL_4; | |
| break; | |
| case VOLUME_LEVEL5: | |
| real_volume = VOLUME_LEVEL_5; | |
| break; | |
| case VOLUME_LEVEL6: | |
| real_volume = VOLUME_LEVEL_6; | |
| break; | |
| case VOLUME_LEVEL7: | |
| real_volume = VOLUME_LEVEL_7; | |
| break; | |
| default: | |
| syslog(LOG_ERR, "Not the correct parameter"); | |
| return 0; | |
| } | |
| return real_volume; | |
| } | |
| int lynq_spk_volume_up() | |
| { | |
| int real_volume,current_volume; | |
| current_volume = lynq_get_spk_current_volume(); | |
| if(VOLUME_LEVEL7 == current_volume) | |
| { | |
| return 1; | |
| } | |
| else | |
| { | |
| lynq_set_spk_volume_to_nvram(current_volume+1); | |
| real_volume = get_spk_real_volume(current_volume+1); | |
| lynq_set_spk_real_volume(real_volume); | |
| return 0; | |
| } | |
| } | |
| int lynq_spk_volume_down() | |
| { | |
| int real_volume,current_volume; | |
| current_volume = lynq_get_spk_current_volume(); | |
| if(VOLUME_LEVEL1 == current_volume) | |
| { | |
| return 1; | |
| } | |
| else | |
| { | |
| lynq_set_spk_volume_to_nvram(current_volume-1); | |
| real_volume = get_spk_real_volume(current_volume-1); | |
| lynq_set_spk_real_volume(real_volume); | |
| return 0; | |
| } | |
| } | |
| int lynq_set_spk_volume(const int volume) | |
| { | |
| if((volume>VOLUME_LEVEL7)||(volume<VOLUME_LEVEL1)) | |
| return 1; | |
| lynq_set_spk_volume_to_nvram(volume); | |
| int real_volume = get_spk_real_volume(volume); | |
| lynq_set_spk_real_volume(real_volume); | |
| return 0; | |
| } | |
| int lynq_get_spk_volume(int* volume) { | |
| if(volume==NULL) | |
| { | |
| return 1; | |
| } | |
| (*volume) = lynq_get_spk_current_volume(); | |
| return 0; | |
| } | |
| static int media_stop_full(MEDIA_PARAM_T *param) | |
| { | |
| GMainLoop *loop = param->loop; | |
| GstElement *playbin = param->playbin; | |
| guint bus_watch_id = param->bus_watch_id; | |
| GstEvent *event_stop = NULL; | |
| if (param != param->handle) { | |
| RLOGE("invalid handle: %p \n", param->handle); | |
| return 1; | |
| } | |
| param->handle = NULL; | |
| gst_element_set_state (playbin, GST_STATE_NULL); | |
| gst_object_unref (GST_OBJECT (playbin)); | |
| g_source_remove (bus_watch_id); | |
| g_main_loop_unref (loop); | |
| free(param); | |
| param = NULL; | |
| g_media_handle=NULL; | |
| return 0; | |
| } | |
| void* media_thread_func(void *arg) | |
| { | |
| MEDIA_PARAM_T *param = (MEDIA_PARAM_T *)arg; | |
| RLOGD("%s start \n", __FUNCTION__); | |
| g_main_loop_run (param->loop); | |
| RLOGD("g_main_loop_run end \n"); | |
| media_stop_full(param); | |
| return ((void *)0); | |
| } | |
| static void start_main_loop(const MEDIA_PARAM_T *param) | |
| { | |
| pthread_attr_t attr; | |
| pthread_attr_init( &attr ); | |
| pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); | |
| pthread_create(&(param->thread), &attr, (void *)media_thread_func, param); | |
| } | |
| int lynq_media_play_audio(const char *path) | |
| { | |
| GstBus *bus; | |
| GstMessage *msg; | |
| GMainLoop *loop; | |
| GstElement *playbin; | |
| gchar *uri; | |
| guint bus_watch_id; | |
| int ret; | |
| pthread_t thread; | |
| int cnt; | |
| MEDIA_HANDLE handle = NULL; | |
| MEDIA_PARAM_T *param; | |
| if(g_media_handle!=NULL) | |
| { | |
| RLOGE ("media is running.\n"); | |
| return 1; | |
| } | |
| param = malloc(sizeof(MEDIA_PARAM_T)); | |
| if (param == NULL) { | |
| RLOGE ("malloc MEDIA_PARAM_T fail \n"); | |
| return 1; | |
| } | |
| memset(param, 0, sizeof(MEDIA_PARAM_T)); | |
| handle = (MEDIA_HANDLE)param; | |
| g_media_handle=handle; | |
| param->mute = 0; | |
| param->volume = 1.0; | |
| gst_init (NULL, NULL); | |
| loop = g_main_loop_new (NULL, FALSE); | |
| playbin = gst_element_factory_make ("playbin", "playbin"); | |
| RLOGD ("main start.\n"); | |
| if (!playbin) { | |
| g_printerr ("Not all elements could be created.\n"); | |
| free(param); | |
| g_media_handle=NULL; | |
| return 1; | |
| } | |
| if (gst_uri_is_valid (path)) | |
| uri = g_strdup (path); | |
| else | |
| uri = gst_filename_to_uri (path, NULL); | |
| g_object_set (playbin, "uri", uri, NULL); | |
| g_object_set (playbin, "flags",0x42,NULL); | |
| g_object_set (playbin, "volume",param->volume,NULL); | |
| g_object_set (playbin, "mute",param->mute,NULL); | |
| bus = gst_element_get_bus (playbin); | |
| bus_watch_id = gst_bus_add_watch (bus, bus_call, (gpointer)param); | |
| g_object_unref (bus); | |
| param->playbin = playbin; | |
| param->bus_watch_id = bus_watch_id; | |
| param->thread = thread; | |
| param->loop = loop; | |
| param->handle = handle; | |
| start_main_loop(param); | |
| RLOGD ("gst_bus_add_watch.\n"); | |
| gst_element_set_state (playbin, GST_STATE_PLAYING); | |
| cnt=0; | |
| do { | |
| if (param->gst_cur_state == GST_STATE_PLAYING) | |
| { | |
| break; | |
| } | |
| else | |
| { | |
| if (cnt==6){ | |
| RLOGD ("After 6s, not enter playing state.\n"); | |
| lynq_media_stop_audio(); | |
| return 1; | |
| } | |
| cnt++; | |
| sleep(1); | |
| } | |
| } while (1); | |
| RLOGD ("lynq_media_play_audio end, handle is %p\n",handle); | |
| return 0; | |
| } | |
| void lynq_media_stop_audio() | |
| { | |
| if (g_media_handle == NULL) { | |
| RLOGE ("%s, g_media_handle is NULL\n", __FUNCTION__); | |
| return; | |
| } | |
| MEDIA_PARAM_T *param = (MEDIA_PARAM_T *)g_media_handle; | |
| if (g_media_handle != param->handle) { | |
| RLOGE("invalid handle: %p \n", g_media_handle); | |
| } | |
| g_main_loop_quit (param->loop); | |
| pthread_join(param->thread, NULL); | |
| RLOGD ("lynq_media_stop_audio end\n"); | |
| return; | |
| } | |